Hi! Hope you're enjoying this blog. I have a new home at www.goldsborough.me. Be sure to also check by there for new posts <3

Monday, July 8, 2013

Tutorial: Simple PyQt text editor

What's the project?

The next app I want to show you how to make, is a simple text editor. The many many many functions will include creating new texts, saving them and EVEN ... wait for it ... opening texts! I kid you not! No seriously, the emphasis is on simple, so it will include really nothing but the basic necessities. I plan on doing a tutorial on an advanced text editor right after. 

What we will be making:



Let's get started

Since we're really only taking advantage of the plug n' play features PyQt gives us, there is no need for creating a logic-only version like I did in the previous tutorial, and it would be more of a project itself actually.

The code:

import sys
from PyQt4 import QtGui, QtCore

class Main(QtGui.QMainWindow):

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.initUI()

    def initUI(self):
        
        newAction = QtGui.QAction('New', self)
        newAction.setShortcut('Ctrl+N')
        newAction.triggered.connect(self.newFile)
        
        saveAction = QtGui.QAction('Save', self)
        saveAction.setShortcut('Ctrl+S')
        saveAction.triggered.connect(self.saveFile)
        
        openAction = QtGui.QAction('Open', self)
        openAction.setShortcut('Ctrl+O')
        openAction.triggered.connect(self.openFile)
        
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('File')
        fileMenu.addAction(newAction)
        fileMenu.addAction(saveAction)
        fileMenu.addAction(openAction)

        self.txt = QtGui.QTextEdit(self)
        self.setCentralWidget(self.txt)
        
#---------Window settings --------------------------------
        
        self.setGeometry(300,300,300,300)
        self.setWindowTitle("Simple Text Editor")
        self.show()

#---------Slots-------------------------------------------

    def newFile(self):
        self.txt.clear()
        
    def saveFile(self):
        filename = QtGui.QFileDialog.getSaveFileName(self, 'Save File')
        f = open(filename, 'w')
        filedata = self.txt.toPlainText()
        f.write(filedata)
        f.close()
        
        
    def openFile(self):
        filename = QtGui.QFileDialog.getOpenFileName(self, 'Open File')
        f = open(filename, 'r')
        filedata = f.read()
        self.txt.setText(filedata)
        f.close()

        
def main():
    app = QtGui.QApplication(sys.argv)
    main = Main()
    main.show()

    sys.exit(app.exec_())

if __name__ == "__main__":
    main()


To get a basic window, copy the code that I prepared on the sidebar of this blog. Next, we have to create a menubar.

menubar = self.menuBar()
fileMenu = menubar.addMenu('File')

To do this, assign self.menuBar() to the variable menubar and add the menu fileMenu with the menubar.addMenu() command, which takes the name of the menu (displayed in the program) as parameter.Then, we have to create the options this menu will have.

        newAction = QtGui.QAction('New', self)
        newAction.setShortcut('Ctrl+N')
        newAction.triggered.connect(self.newFile)
        
        saveAction = QtGui.QAction('Save', self)
        saveAction.setShortcut('Ctrl+S')
        saveAction.triggered.connect(self.saveFile)
        
        openAction = QtGui.QAction('Open', self)
        openAction.setShortcut('Ctrl+O')
        openAction.triggered.connect(self.openFile)

This is done just as quick. Create three variables, three actions (that is usually how menu options are called), and assign them to QtGui.QAction(), which takes the name of the action and the parent as parameters, in this case self. Optionally, you can set shortcuts to these actions like I did with setShortcut, and also make a message appear in the status bar while hovering them using setStatusTip (if you created a statusbar before). Then, connect the actions to slot functions using triggered.connect(), with the function as parameter. We will take care of the functions in a minute.

Before creating the functions, we have to add the actions to the menu.

        fileMenu.addAction(newAction)
        fileMenu.addAction(saveAction)
        fileMenu.addAction(openAction)

Next, it'd be nice to have something to write on.

self.txt = QtGui.QTextEdit(self)
self.setCentralWidget(self.txt)

Simply create a QTextEdit like I did above and assign it to self.text. To make it the main widget of this window, use setCentralWidget, a very interesting function of PyQt that replaces having to position and re-size a widget.

Lastly and most importantly, the functions we previously assigned to the actions have to be created. They won't just appear you know. You can pray to the python god all you want, it just won't happen ... and if there is none, people interested in creating a cult contact me IMMEDIATELY. Nonetheless, the question has to be raised: Why did the programmer die of starvation in the shower? His shampoo said: lathe, rinse, repeat. The functions:

    def newFile(self):
        self.txt.clear()
        
    def saveFile(self):
        filename = QtGui.QFileDialog.getSaveFileName(self, 'Save File')
        f = open(filename, 'w')
        filedata = self.txt.toPlainText()
        f.write(filedata)
        f.close()
        
        
    def openFile(self):
        filename = QtGui.QFileDialog.getOpenFileName(self, 'Open File')
        f = open(filename, 'r')
        filedata = f.read()
        self.txt.setText(filedata)
        f.close()


  1. The "new file" action. Visibly the easiest of them all. The QTextEdit is simply cleared and thus makes space for a new text.
  2.  The "save file" action. To save a file in PyQt, we need to call a QFileDialog, which we assign to the filename variable. Since we're saving the file, we use the static function getSaveFileName of the QFileDialog, which takes the parent class and the name of the file dialog as parameters. Since we want to save the text that we wrote, we also need some file I/O. So open the file in "w" (for write) mode as the variable f and insert filename as the name of the file, taking the name we save it as in the QFileDialog. To get the text in the QTextEdit, use toPlainText() and assign it to another variable filedata. Lastly, write the the text that is assigned to the variable filedata to the file using f.write and close the file.
  3. The "open file" action. This is similar to the function before, just that we are now opening a file. So, instead of getSaveFileName, we now need getOpenFileName for the QFileDialog. Then, open the file as f again but in r, for read, mode this time. Read the text in the file using f.read() and assign this text to the variable filedata again. Then, we need to display the text from that file in the QTextEdit. Do this by using setText(filedata). Don't forget to close the file. 
Run the program and have a couple hours planned in to discover the numerous functions this little program has.

I hope I explained everything very clearly and your text editor works just as expected. Yes you could use your operating system's text editor, but there's a very simple answer to the question why you would use yours instead: Because it's yours. 



1 comment :