I am relatively new to Python. Moreover, I use it in Windows and I don't feel guilty about it. I wanted to learn how to create a simple user interface in Python. I looked up on the Internet and found a number of good tutorials. However, I had to look quite a lot for a tutorial for beginners. And as a consequence, I decided to write a simple tutorial for this purpose. I do assume previous Python and GUI building experience (in a different language).
I have pythonxy on my Windows 7 computer together with QtDesigner. I use Spyder for editing the code and running it. However, if you are a fan of anaconda distribution, then it is possible to do it there too (QtDesigned comes installed in C:\Users\<your user>\Anaconda3\Library\bin\designer.exe).
In this tutorial, we will create a very simple, demonstration-only user interface in QtDesigner and add event handlers for it in Python. There will be two buttons: clicking on one of the buttons will write some text on the interface whereas clicking on the other one will clear it.
Here are the steps:
1. Open QtDesigner
2. Click File > new and select "Dialog without buttons" on the resulting New Form dialog.
3. Add two buttons from the widget box on the left and name the buttons "cmdWrite" and "cmdClear" with the display text set to "Write" and "Clear" respectively. You can search for different controls by typing their names (such as 'button') in the text box on the widget box.
4. Add a text label (name it lblShow), a line edit box (name it txtLine) and a text edit Box (name it txtEdit).
5. Arrange the controls by aligning them horizontally and vertically as shown below.
6. One good thing about Qt Desginer is that you can attach some functionality to your GUI without writing any code. For example, we would like the clear button to clear the text in all the text controls. This can be accomplished very easily by clicking on the "Edit signals and slots" button on the "Tools" toolbar in the Qt Designer interface. This can also be accomplished by pressing F4 on the keyboard.
7. Click on cmdClear and a red line will appear. Connect the cmdClear through this line to a text control (say lblShow) using the mouse. Once the connection is complete, a "Configure Connection" dialog will appear and you can select the "clicked()" signal in the left pane and the "clear()" slot in the right pane. Now when you click on the cmdClear, the clear() function of the lblShow will be called automatically and this will clear the label. You can test this simple functionality in the Qt Designer by pressing Ctrl+R and clicking on the Clear button. Do the same for txtLine and txtEdit. Below is a screen shot of how this will look in Qt Designer.
8. Save the project to "hw.ui".
9. Create the python code for hw.ui by using the following command in a command window (not in python or ipython interpreters):
> pyuic4 -x hw.ui -o hw.py
This command creates a file "hw.py" which contains the python code corresponding to the Qt GUI you have created. You can run the GUI using python by typing python hw.py in command window. It will show the same GUI as seen in the preview from Qt Designer. You can click on clear to clear the label. If you are using PyQt5 (comes with Anaconda distributions), you can run the equivalent command as follows by first accessing the base directory for pyuic5. You may also need to specify appropriate paths to your files:
C:\Users\<your user>\Anaconda3\Library\bin>pyuic5 -x c:\Users\<your user>\Desktop\hw.ui
-o c:\<your user>\afsar\Desktop\hw.py
10. If you need more assistance on steps 1-7 you can view this excellent video which I came across during my quest.
11. The python file hw.py is shown below.9. Create the python code for hw.ui by using the following command in a command window (not in python or ipython interpreters):
> pyuic4 -x hw.ui -o hw.py
This command creates a file "hw.py" which contains the python code corresponding to the Qt GUI you have created. You can run the GUI using python by typing python hw.py in command window. It will show the same GUI as seen in the preview from Qt Designer. You can click on clear to clear the label. If you are using PyQt5 (comes with Anaconda distributions), you can run the equivalent command as follows by first accessing the base directory for pyuic5. You may also need to specify appropriate paths to your files:
C:\Users\<your user>\Anaconda3\Library\bin>pyuic5 -x c:\Users\<your user>\Desktop\hw.ui
-o c:\<your user>\afsar\Desktop\hw.py
10. If you need more assistance on steps 1-7 you can view this excellent video which I came across during my quest.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | # -*- coding: utf-8 -*- hw.py
# Form implementation generated from reading ui file 'hw.ui'
#
# Created: Sat Aug 11 14:06:40 2012
# by: PyQt4 UI code generator 4.8.6
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName(_fromUtf8("Dialog"))
Dialog.resize(368, 319)
Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
self.cmdClear = QtGui.QPushButton(Dialog)
self.cmdClear.setGeometry(QtCore.QRect(140, 10, 75, 23))
self.cmdClear.setText(QtGui.QApplication.translate("Dialog", "Clear!", None, QtGui.QApplication.UnicodeUTF8))
self.cmdClear.setObjectName(_fromUtf8("cmdClear"))
self.widget = QtGui.QWidget(Dialog)
self.widget.setGeometry(QtCore.QRect(60, 100, 258, 213))
self.widget.setObjectName(_fromUtf8("widget"))
self.verticalLayout = QtGui.QVBoxLayout(self.widget)
self.verticalLayout.setMargin(0)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.txtEdit = QtGui.QTextEdit(self.widget)
self.txtEdit.setObjectName(_fromUtf8("txtEdit"))
self.verticalLayout.addWidget(self.txtEdit)
self.lblShow = QtGui.QLabel(self.widget)
self.lblShow.setText(QtGui.QApplication.translate("Dialog", "TextLabel", None, QtGui.QApplication.UnicodeUTF8))
self.lblShow.setObjectName(_fromUtf8("lblShow"))
self.verticalLayout.addWidget(self.lblShow)
self.widget1 = QtGui.QWidget(Dialog)
self.widget1.setGeometry(QtCore.QRect(80, 50, 216, 25))
self.widget1.setObjectName(_fromUtf8("widget1"))
self.horizontalLayout = QtGui.QHBoxLayout(self.widget1)
self.horizontalLayout.setMargin(0)
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.txtLine = QtGui.QLineEdit(self.widget1)
self.txtLine.setObjectName(_fromUtf8("txtLine"))
self.horizontalLayout.addWidget(self.txtLine)
self.cmdWrite = QtGui.QPushButton(self.widget1)
self.cmdWrite.setText(QtGui.QApplication.translate("Dialog", "Write!", None, QtGui.QApplication.UnicodeUTF8))
self.cmdWrite.setObjectName(_fromUtf8("cmdWrite"))
self.horizontalLayout.addWidget(self.cmdWrite)
self.retranslateUi(Dialog)
QtCore.QObject.connect(self.cmdClear, QtCore.SIGNAL(_fromUtf8("clicked()")), self.txtLine.clear)
QtCore.QObject.connect(self.cmdClear, QtCore.SIGNAL(_fromUtf8("clicked()")), self.txtEdit.clear)
QtCore.QObject.connect(self.cmdClear, QtCore.SIGNAL(_fromUtf8("clicked()")), self.lblShow.clear)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
pass
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
Dialog = QtGui.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
|
Most of the code is responsible for creating and positioning the controls on the dialog. However, lines 54-56 are responsible for the 'clearing' behavior resulting from clicking cmdClear.
12. How to add more functionality? One way would be to edit the file (hw.py) created using pyuic4. However, there are two types of problems in doing this:
a. Modifications of the GUI: Whenever you change the GUI, you would have to re-run pyuic4 to update hw.py and this will clear out any changes you have made. Hence the warning on line number 8.
b. Object oriented correctness: Suppose you were implementing a browser and you chose to make changes to hw.py to implement the application logic. Then this will make your application logic and your user interface to be intertwined.
13. A better way to solve this issue is to create another file say hwlogic.py as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # -*- coding: utf-8 -*- hwlogic.py
"""
@author: Afsar
This is the Implementation logic for Hello World! (hw.py)
"""
from PyQt4 import QtCore,QtGui
import sys
import hw
class hwl(QtGui.QDialog,hw.Ui_Dialog):
"""
hwl is inherited from both QtGui.QDialog and hw.Ui_Dialog
"""
def __init__(self,parent=None):
"""
Initialization of the class. Call the __init__ for the super classes
"""
super(hwl,self).__init__(parent)
self.setupUi(self)
self.connectActions()
def main(self):
self.show()
def connectActions(self):
"""
Connect the user interface controls to the logic
"""
self.cmdWrite.clicked.connect(self.myprint)
def myprint(self):
"""
Even handler for the pushButton click
"""
self.txtLine.setText('Python -- ')
self.txtEdit.setText('This')
self.lblShow.setText('is a test')
if __name__=='__main__':
app = QtGui.QApplication(sys.argv)
hwl1 = hwl()
hwl1.main()
sys.exit(app.exec_())
|
In this file, we have created a class 'hwl' which inherits from both QtGui.QDialog and hw.Ui_Dialog. Remember hw.Ui_Dialog is the name of the class in hw.py which contains the user interface constructs. The __init__ function of hwl does the following:
line 17: Calls the __init__ functions of the super classes of hwl.
line 18: Calls the setupUi function implemented in hw.py which is responsible for setting up the controls on the dialog and also associating some functionality (the clearing resulting from clicking cmdClear) to the controls.
line 19: Connects the application logic (actions) to the controls by calling the function self.connectActions(). The connectActions function links the execution of the function myprint to the click of the cmdWrite button (line 27). The myprint function writes three different texts to the three text controls (line 32-34). One can also add the clearing of these controls linked to the clicking of cmdClear to the connectActions functions to completely disassociate the application logic from the user interface.
lines 35-39: Create an application and an instance of the hwl class and call its main function which brings up the application and runs it.
14. You can now run the 'hwl.py' file to see the results of our labor.
Acknowledgements: Most of the ideas for this tutorial are taken from:
Videos by Kris.
Tutorial by Harsh J.
The code was published using pygmentize through the following command (example):
pygmentize -O full=true,style=colorful, linenos=1 -o hwlogic.html hwlogic.py
I welcome comments and criticism. The code was published using pygmentize through the following command (example):
pygmentize -O full=true,style=colorful, linenos=1 -o hwlogic.html hwlogic.py
Nice. I use PythonCards. I find it simple and worthy.
ReplyDeleteThanks Hisham. I had never used that. I did take a look at a PyCards tutorial (http://pythoncard.sourceforge.net/walkthrough2.html). Seems like connecting the even handlers to the events is easier in PyCards. But haven't tried it myself yet. :)
ReplyDeletehow we can create ahyperlink in qt desinger
ReplyDeleteHelpful--many thanks
ReplyDeleteThank you! This was very helpful - especially the part about decoupling the UI and the logic.
ReplyDeleteHi there,
ReplyDeleteI got strucked in the 9th step. Where do you want me to type the "> pyuic4 -x hw.ui -0 hw.py" code?. In windows command prompt ?. You said that not to type in python IDLE or IPython , then where can i type this code?. In my windows command prompt, i got the answer that, '-x' is not recognized as an internal or external command, operable program or batch file. Please help
Hi there,
ReplyDeleteAt last, i have got it. I have googled abot 3 hours and find the real problem. I need to enter the code in cmd, but i need to specify the path of the input and output. You said here that to enter only file name that is hw.ui. But that didn't work. You must enter the path like pyuic4 -x C:\users\xxxx\Desktop\hw.ui -o D:\New Folder\hw.py. Anyway i just pulled away the obstacles in my way and want to learn more.
there is a typo, 14 should read "You can now run the 'hwlogic.py' file to see the results of our labor.", not 'hwl.py'
ReplyDeleteThank you for posting this. I am just starting with QT designer/python. This was extremely helpful and separating the design from the logic.
ReplyDeleteDoes the hwlogic.py also solve the Data Problem when converting after editing the .py file (Point 12a)?
ReplyDelete