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.
Python, Qt and PyQt
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.