As simple as they come

Nothing like getting the feet wet: let's investigate the structure of a PyQt application by putting together the minimal set of components that can show something on screen, slowly expanding it to show more features.

A tiny PyQt applications has the following elements:

This is the traditional ”Hello World” button application, with as little code as possible:

Hello World

Example 6-1. hello1.py — hello world

#
# hello1.py
#
import sys                                                 (1)
from qt import *                                           (2)

app=QApplication(sys.argv)                                 (3)
button=QPushButton("Hello World", None)                    (4)
app.setMainWidget(button)                                  (5)
button.show()                                              (6)
app.exec_loop()                                            (7)
        
(1)
We need to import the Python sys package, because the QApplication object wants to look at the command-line arguments the script is started with. For instance, starting the script with python hello1.py -style=platinum starts the script with the look and feel of Mac-OS 8.5, by passing the “-style=platinum” option through to the QApplication object.

One of the niceties of Qt is that you have access to all supported widget styles on all platforms. (Except for the Aqua style - that is only available on OS X, because Apple doesn't want it to spread to other platforms.)

(2)
Next, we have to import the qt library. While it is possible to import only explicitly the elements from the library we need, it's just as easy and efficient to import the whole library. But we could have said:
 from qt import QApplication,
                QPushButton 

From version 3.x of PyQt, the library has been split into several separate modules. The Qt module still gets you all the basic stuff, but more advanced functionality, such as the canvas, is divided over separate modules, qtcanvas for QCanvas, for instance.

(3)
After importing the necessary modules, we create a Qt application object. This object handles the dispatching of events from the mouse and keyboard to the various widgets of the application. Never try to create more than one QApplication object, not even if you embed Python and PyQt in a C++ Qt application. In that case, the C++ application should create the QApplication object and pass a reference to the embedded Python interpreter.
(4)
To keep things simple, we do not create a separate window object, but rather simply a pushbutton, of the type QPushButton. The first argument to the creation of the QPushButton is the text that is shown on the button. Since this is the only widget of the application, it doesn't have a parent. This is what the None argument means — there is no parent, and the QPushButton is the root of the application widget tree.
(5)
However, we still need to apprise the QApplication object of that fact — this is done by telling the QApplication that our button is the main widget:
app.setMainWidget(button)
            
(6)
Then we show() the button to the world.
(7)
Until the application objects starts the event loop, nothing will appear on screen. The call app.exec_loop() does return a value, but we can safely disregard it.

Note: Note that this is one of the few instances where a method name differs between Python and C++: the C++ method is called exec(), which is a reserved word in Python. Except for a few cases like this, reading the C++ documentation for Python use demands little more than a simple mental substitution.

Experienced Pythoneers will also note that the parameters in PyQt function calls are positional — not by keyword. In the old Tkinter GUI toolkit most function calls take the form:

b = Button(root, text=label, command=func)
        

where PyQt wants:

b = QPushButton(root, label, func)
        

Just something to be aware of: keyword parameters can be added in any old order, but positional parameters have to be in the right position.