Appendix A. Reading the Qt Documentation
Qt is originally a C++ GUI toolkit,
and PyQt is just a wrapper around it. Fortunately, Qt is very well
designed and makes full use of the object-oriented qualities of
C++, so the translation is very comfortable, and PyQt feel like a
real Python library.
BlackAdder includes a copy of the Qt
class documentation (nineteen megabytes of html text) that has
been fully translated to Python. Of course, if you want to use a
more recent version of PyQt than that which comes with BlackAdder,
or if you use PyQt on itself, then you need to read the C++
documentation for all the details that I didn't have space to
discuss in this book. After all, this book teaches you how to use
the toolkit to create complete applications, and isn't a mere
duplication of the class documentation.
Fortunately, reading C++
documentation for use from Python isn't very difficult. In fact,
the translation to Python idiom that is included with BlackAdder
has been achieved for the greater part with a few find & replace
scripts. However, if your knowledge of C++ (or C) is limited to
knowing that it exists, then you might want to read this appendix
for some guidance.
Using KDE to have quick access to the Qt
documentation: If you are using KDE on Unix/X11,
you can create new internet shortcuts that take you to the Qt
class documentation in an instant.
KDE has a wonderful feature,
called the run command window, in which you can type a short
abbreviation (like "gg" for the Google search engine), followed
by a colon and an argument.
If you add
"file://usr/lib/qt2/doc/html/\1.html" in
KControl, section Web
Browsing/Enhanced Browsing:
Then you will be able to access al
Qt documentation by typing "qt:qobject", for instance. What you
are typing is the name of the html document that contains the
class information: all these documents have the classname as a
filename, all in lowercase.
Note that the shortcut
(file://usr/lib/qt2/doc/html/\1.html) should point to the place
where your qt (or BlackAdder - that would work too)
documentation resides. The element after the directory path
(\1.html) is a simple substitution argument— \1 is
replaced by what you type after the colon.
You can quickly access the run
command window by pressing ALT-F2 in KDE's standard
configuration.
Let's take a simple Qt class as an
example: QLabel. It's a good idea to open
the Qt class documentation in your browser window (remember the
KDE shortcut) and keep that in view.
First, the documentation tells you
that the QLabel class includes
qlabel.h: #include
<qlabel.h>. This means about the same as a
Python import statement. You can disregard it.
The methods that do not return
anything, but have the same name as the class, are the C++
constructors. Simply call them with the right arguments. Don't pay
attention to any spurious asterisks (*) or ampersands (&) around
the arguments to the function: what matters is the type, like
QWidget. Don't pay attention to the
const keyword either.
If there is an equals sign (=)
after the variable name, then the function can use a default
parameter, just like in Python. Again, just like in Python,
booleans are zero or one. However, a default
argument of zero, has a default argument of None in Python. This
is important if you want to use two out of three arguments: then
you must also mention the middle man (you can safely drop any
tailing default arguments you don't need):
label=QLabel("text", None, "name")
versus
label=QLabel("text")
Public members are instance methods
of objects. If you call a public member, you should always prefix
the call with the name of the object you have created (or
self if you are calling the method from within
the object). For example:
print label.text()
Slots are in no way different from
ordinary functions in Python, so what holds for public members
also holds for public slots. Protected member variables are a
vague kind of private—if you create the
QLabel from Python, you can access the
protected members, like drawContents(), without
problems, but if the QLabel has been
created from a C++ class then you cannot access the protected
member functions.
Properties are currently not
supported by PyQt—everything you can set and get with
properties is also accessible by get() and
set() methods.
If you are reading the detailed
description of a class, you will often come across snippets of C++
code. These are easy to translate, too. Just keep in mind that
both a double semi-colon (::) or an arrow (->) translate to a
Python dot (.). And you don't need braces or final semicolons, of
course. Or new statements. For
instance:
QLabel *label = new QLabel;
label->setFrameStyle( QFrame::Panel | QFrame::Sunken );
label->setText( "first line\nsecond line" );
label->setAlignment( AlignBottom | AlignRight );
Could become in Python:
label = new QLabel()
label.setFrameStyle( QFrame.Panel or QFrame.Sunken )
label.setText( "first line\nsecond line" )
label.setAlignment( Qt.AlignBottom or Qt.AlignRight )
Note also that certain pre-defined
values, called constants in C++ (and lots of other languages), are
placed either in a certain class, not
object instances or in the
Qt pseudoclass. Thus, the
Panel or Sunken constants
are accessed from the QFrame class, while
the AlignBottom and
AlignRight constants are taken from the
Qt pseudoclass. Note also that it isn't
necessary to prefix Qt in C++, but that
this is obligatory in Python.
A bit like constants are
static methods, and are defined on the
class:
QObject.connect()
QLabel
doesn't have any signals or static members. For those we had
better look at another class:
QScrollbar.
Signals have already been discussed
in detail in Chapter 7. Here I only want to mention the
way you must remove any fluff from the declaration. Signals are
placed in a Python dictionary by sip,
so you really want to get the string argument to
SIGNAL() right.
So, if there are no arguments to
the signal, you can just copy it, including the brackets. If there
are arguments you need to copy the entire argument list, but not
the variable name. So:
void valueChanged ( int value )
Can be used as:
QObject.connect(sbar,SIGNAL("valueChanged(int)"),someFunction)
On the other hand, if there are
asterisks involved, then you have to copy those, too. In
QListView,
void returnPressed ( QListViewItem * )
Becomes:
self.connect(self,
SIGNAL("returnPressed(QListViewItem *)"),
self.slotItemSelected)
The Qt documentation is not always
consistent in giving signal parameters variable names - sometimes
they do, sometimes they don't.
Finally, wherever there is a NULL
in C++, you can use None, but you can also use None in many cases
where there is a zero (0) (this being a pointer to nowhere). That
means that everywhere a function takes an object (instead of a
simple integer) as a parameter, you can use None. A zero is often
given as a default argument in these cases, and then you don't
need to give any parameter. Thus:
QListView ( QWidget * parent = 0, const char * name = 0 )
Can be called as:
listview = QListView(None, None)
or:
listview = QListView()
You can also use actual arguments,
of course. You almost never need to actually pass something for
the name parameter, but it makes for nicer
debugging:
listview = QListView(parentWindows, "listview")
As you've seen, it's not difficult at all to translate from
C++ to Python — even if you don't know any C or C++. If you
do want to know more about C++, I can recommend Steven Oualline's
book, Practical C++ Programming as a good
beginners title.