Tutorial: Creating GUI Applications in Python with QT
by Alex Fedosov
Python is a great language with many awesome features, but its default GUI package
(TkInter) is rather ugly. Besides, who wants to write all that GUI code by hand, anyway?
Instead, a much better way to write GUI apps in Python is to use Trolltech's QT Designer
to WYSIWYG-ly create a nice-looking interface, and then automatically generate the
necessary code for it with pyuic (which is a UI compiler for QT that comes with the PyQT
package.) QT designer also makes it very easy to add Python code to your project. (If you
want your app to do anything useful, you will undoubtedly need to write some code. :) )
So the following is a brief tutorial on how to go about creating your first semi-interesting
application with Python & QT.
We are going to create a little application that will take input from the user, add said input to a
list box and also allow the user to clear the contents of the list box.
First, you need to have the following packages installed:
QT Designer 3.x
I did everything with default packages that came with Fedora Core 1, and had no
problems. Also tested on RedHat 9 with no problems. YMMV. (Note: RedHat 8.0 should
also work, but it has an older version of QT designer, which is not as nice as the one in
RH9 and FC1.)
So if you have everything, we can go ahead and get started. Launch QT designer. In
RedHat 9 and Fedora Core 1, it lives under Programming/More Programming menu.
PyQT Tutorial 1
QT Designer will come up. It looks like this.
In the New/Open dialog box, click on Dialog, and hit OK.
PyQT Tutorial 2
QT Designer will create a new dialog canvas for you and call it Form1.
In the toolbar on the left select the LineEdit tool and create an edit box on the canvas. Its
PyQT Tutorial 3
name will be lineEdit1. This is how we will take input from the user.
Now, select the ListBox tool in the toolbar on the left and create a list box on the canvas.
Its name will be listBox1. This is where we will store the input that the user typed in.
PyQT Tutorial 4
Notice that there is already an item in the box. We don't need it. Let's get rid of it.
Double-click on your list box on the canvas. A dialog will pop up showing the contents of
the list box. Hit Delete Item to get rid of the item. Then click OK.
Now, select the PushButtontool in the toolbar on the left and create a button on the
canvas. Its name will be pushButton1.
PyQT Tutorial 5
Double-click on the button on the canvas. A dialog will come up where you can change the
text displayed on the button. Let's rename it to X. Then click OK.
Now, let's make the button do something. In QT terminology, our button will send a
signal which will be received by a slot. (Think of a slot as a method of an object that will
get called in response to an event, like user clicking the button.) Remember that we want
to clear the list box when the user clicks the button. There are already built-in methods for
this, so we'll take advantage of them. To connect a signal to a slot we use the connect tool
PyQT Tutorial 6
which is the red arrow on the green rectange in the top toolbar on the right. It looks like
Here's the tricky part. After selecting the tool, click on your X button on the canvas, and
drag the mouse (without releasing) to your listbox on the canvas. Once you are over the
listbox (it will be highlighted), you will see a line from the button to the listbox, and you
can release the mouse. Another dialog box will pop up where you can specify exactly
which signal and slot you want to connect. Select pushButton1 as the sender, clicked()
as the signal, listBox1 as the receiver and clear() as the slot. Then click OK. (The
meaning of this is that we want to delete all contents of the box when the user clicks the
In the previous step, we used a built-in slot to accomplish something. Now, let's create our
own slot, which will take input from the edit box and add it to the list box when the user
presses enter after typing something. To create a new slot (remember, it's just a method),
select Slots from the Edit menu.
PyQT Tutorial 7
A dialog listing custom slots will show up. Initially, it will be empty. Let's add a new slot
by clicking New Function. Let's call this function AddEntry() (don't forget the parentheses
when typing in the new name) because it will add a new item to the list box. Don't change
any other settings and just click OK. (We'll write the code for this method later on.)
Now that we have a slot, we can connect something to it. Recall that we want to add an
PyQT Tutorial 8
item to the list when the user types something in the edit box and presses Enter. Select our
good friend the connect tool and now connect the line edit to the list box. The connection
dialog will pop up again. This time select lineEdit1 as the sender, returnPressed() as
the signal, Form1 as the receiver, and our own AddEntry() as the slot.
Finally, we are ready to write some code. We need to implement our AddEntry() method.
In the Project Overview window in the top right-hand corner, double-click on the
form1.ui.h file. (The second one, under your main file.) A window will pop up showing
the text of this file. This file is where you implement all your custom slots, which will then
be included during the compilation process. Notice that QT designer already put in a
header for our AddEntry() function... except that it's in C++! Don't worry about that,
however, we can still write Python code here right between the braces, and it will work
just fine. (Python UI compiler is smart enough to understand the headers generated by QT
designer.) The only problem is that QT designer wants to auto-indent your code, but it
expects semi-colons at the end of line, so naturally Python confuses it and the indentation
gets all screwed up. So alternatively, you can just use your favorite editor (read: vi) to edit
this file. (Or figure out how to turn off auto-indent.)
PyQT Tutorial 9
So what code do we write? We need to accomplish three things:
Grab the text from the line edit
Insert the text into the list box
Clear the line edit
All the slots you define are methods of the dialog box, and all your widgets are objects
within it, and you can just refer to them by their names. So self.lineEdit1 is the line
edit, and self.listBox1 is the list box. The line edit has a method called text() which
returns a QString object representing the text in the line edit. Without going into too
much details about these objects, all we need to know is that a QString object has an
ascii() method which will return the raw ASCII string of the entered text. So to get the
text out of the list box:
e = self.lineEdit1.text().ascii()
Next thing we need to do is add this text to the list box. The list box has a method
insertItem() which takes a string and adds it to the list:self.listBox1.insertItem(e)
Finally, we just clear the line edit with its clear() method:
PyQT Tutorial 10
Almost done! Last thing we need to do is to turn off the autoDefault setting for our delete
button. (Setting a button as default means that it will get 'clicked' if the user presses Enter
on the dialog. For us it would not make sense to add text to the list box on Enter, and then
have the delete button automatically triggered, clearing our list box.) The autoDefault
property is True by default, so we need to set it to False in the Property Editor window
for the button. Click on the button to see the Property window for it in the lower
Finally we are done with QT designer. Save all your work.
Now open up a shell. We want to compile our GUI code into Python code. This is done for
us by the pyuic compiler. Pass the .ui file as an argument, and it will spit out Python
code onto standard output. (So it's more useful to redirect the output to another file.)
pyuic form1.ui > form1.py
Now you end up with form1.py which is a module containing your dialog as a Python
PyQT Tutorial 11
class. Since it has no main() function, you can't run it directly. Instead, we need to create
a simple wrapper for it, like so:
from qt import *from form1 import *import sysif __name__ == "__main__": app = QApplication(sys.argv) f = Form1() f.show() app.setMainWidget(f) app.exec_loop()
Without going into too much detail, we import the QT library Python module, as well as
our dialog class. Then we create a context for our QT application, instantiate our dialog,
show it on the screen, set it as the main widget of the application, and let QT enter its
event loop, processing all the signals and calling our slots. Save this in a separate Python
file, e.g. mygui.py. Needless to say, this wrapper is fairly generic and can be reused for
most of your Python/QT applications. Finally, we are ready to run! Execute your app with:
It should look something like this:
If you type something into the line edit box and press Enter, it should get added to the list
box. If you hit the X button, the list box should be cleared. If it doesn't behave as it should,