Tutorial-Creating GUI Applications in Python With QT

Embed Size (px)

DESCRIPTION

Intro a PyQt

Text of Tutorial-Creating GUI Applications in Python With QT

  • 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:

    Python 2.x

    PyQt 3.x

    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

    this:

    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

    button.)

    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:

    self.lineEdit1.clear()

    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

    right-hand corner.

    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:

    python mygui.py

    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,

    g