This chapter describes the way Python and Qt bind together, using the PyQt wrapper library. Concepts peculiar to PyQt and Qt such as signals and slots, inheritance and gui design, are introduced by building steadily more complex versions of the hackneyed hello world example application.
Unlike a tool like Visual Basic, which consists of a GUI engine with a scripting language built-in, Python does not have a native GUI interface. But there are many GUI libraries available for Python — examples are wxPython, Tkinter, PyGTK, PyFLTK, FoxPy, and PyQt. PyQt is based on Qt, an advanced GUI library for Windows and Unix written in C++ by Eirik Eng and Arnt Gulbrantsen of Trolltech in Norway. It's quite easy to wrap C++ or C libraries so they can be used from Python — and when Phil Thompson was looking around for a good GUI library for Python he decided to wrap Qt, producing PyQt. PyQt forms the basis for the BlackAdder rapid development environment.
Qt is very advanced: the library offers a large set of well-designed screen objects, or widgets, and many utility classes. In addition, Qt has a clean object-oriented design that is easy to grasp and intuitive to use. PyQt applications can run without any change, without recompiling, both on Windows and Unix/X11 systems — and soon on Apple's OS X, too.
PyQt widgets can be drawn in styles, to make them appear exactly like the native widgets of the operating system the application runs on (or like something different altogether, if you want).
There are two kinds of objects in the Qt library— visual and non-visual. The mother of all visual objects is QWidget, widget being the term Qt uses for what the Windows world usually calls control. There are simple widgets such as labels and buttons, and complex widgets such as canvas views. Even dialog windows are descended from QWidget.
QWidget and many other, but not all, Qt classes derive from the QObject base class — a class like QLayout is derived from QObject, but QPixmap is not. Whether a class is derived from QObject is determined by whether there is a need for signals and slots, and whether the created objects must be placed in an ownership hierarchy.
Scripting languages like Python have a reputation for bad performance, but PyQt applications perform very well indeed; there is just a thin wrapper between the GUI objects and Python. Those GUI objects do most of the heavy work of pixel shifting, and they are written in well-optimized C++. If you try to do things like writing your own DTP layout engine from scratch using the Qt drawing primitives, you might be hindered by the slowness inherent in a byte-code interpreted language like Python, but on the whole, your application will be as responsive as one written in pure C++, and you'll have a working application where you would still be hacking the first prototype in C++.
A note on versions: PyQt consists of at least three components, Python, Qt and PyQt itself. Additionally, there is PyKDE, the bindings to the KDE Desktop Environment for Unix. That's four components with almost unrelated version numbering. Qt has been through three versions to date, just like PyQt. However, PyQt 3.x can be compiled against Qt 1.x, Qt 2.x and Qt 3.x.
The differences between versions of PyQt consist of the range of versions of Qt supported, and certain matters of organization and some implementation details.
The relation between PyQt and Python is even more nebulous: PyQt works best with the latest version of Python, but earlier versions are known to work, too.
Anyway, just keep in mind that PyQt 3.x can use Qt 2.x or Qt 3.x. This book was mostly written using PyQt 2.x for Qt 2.x, but I've tried to include as much information about PyQt 3.x and Qt 3.x as I could.