You probably already know that the windowing system that runs on nearly every Linux machine is the X Window System, also known as X11. (See The History of XFree86, to learn about where X11 comes from and how it came to be available on Linux.)
X11, by itself, only implements low-level primitives such as line drawing, color manipulation, event handling, etc. — the basic building blocks that GUIs are made from. It is certainly possible to design a graphical user interface from such small building blocks, but doing so for any substantial application could take more than a lifetime. Nowadays, only two really have a strong following in the open source world — GTK and Qt.
GTK was originally developed as a replacement for Motif that could be used in the GIMP; it has since taken on a life of its own and is currently being developed independently. In fact, many applications now use GTK for their GUIs. GTK also forms the base of the GNOME desktop that is used on some Linux systems. One distinguishing feature of GTK is that it is implemented in C, but in an object-oriented fashion. What the GTK team did was very clever, but can result in awkward situations sometimes. (To find out more about GTK, see our previous article, “Getting GUI with GTK,” at http://www.linux-mag.com/2001-06/gtK_01.html.)
And then there’s Qt. It has a clean, object-oriented programming interface and abundant features. Qt-based applications are very responsive and have an acceptable memory footprint. Qt has proven itself to be viable for large-scale software projects, both commercial and Open Source. For example, the KDE desktop, a very popular desktop environment for Linux and FreeBSD systems, has been developed with Qt. The KOffice productivity suite, an MS Office alternative, was also developed with Qt. These two projects alone amount to more than two million lines of Qt-based code. But enough talk — let’s see some code.
Getting and Installing Qt
Qt is available in two different licenses: There is a GPL version which you can use to write programs that are themselves licensed under the GPL, and there is a commercial version that you can use to write any type of software.
Functionally, there is no difference between the two versions, but the commercial version gives you a right to technical support. In order to get the commercial license, you can contact the manufacturers of Qt at sales@trolltech.com.
If you want to write GPL software (which we will assume here), you can simply download Qt from ftp://ftp.trolltech.com/qt/source/qt-x11-free- 3.0.0.tar.gz. (There might already be a newer version available by the time you read this, see also the Qt Versions sidebar). Unpack the tar file with:
tar xvfz qt-x11-2.3.1.tar.gz
Change to the Qt directory:
cd qt-x11-free-2.3.1
Point the QTDIR environment variable to this directory:
export QTDIR=`pwd`
export QTINC=$QTDIR/include
export QTLIB=$QTDIR/lib
Configure Qt (depending on what you want to do with Qt, you might consider using special switches. Typing configure –help will display all of to the available switches, but for most purposes, the default configuration should work just fine):
./configure
And build Qt:
make
Now you are ready to use Qt.
Please note that most Linux distributions these days already contain Qt, even though some might carry outdated versions. If your Linux distribution has a reasonably recent Qt (which is usually the case for at least the SuSE, Caldera, and Mandrake distributions), you might be able to skip these steps and get to work right away. |
OUR FIRST QT PROGRAM
Qt is a C++ toolkit, so all programs and code snippets you see here will be written in C++. In case you do not like C++, volunteers have written Qt bindings for other languages like C, Perl, and Python, but “real” Qt development almost always involves writing in C++. It provides support for object-oriented constructs without sacrificing run-time efficiency, so it’s a good choice for GUI development.
If you haven’t had much exposure to C++ but know C, you can still follow along. Qt does not use many of C++’s more advanced features. You might want to have a C++ book handy, though, just in case.
Tradition demands that every first programming lesson start with a program that outputs “Hello world,” so we’ll build just that. Listing One contains the code necessary for building a Qt version of “Hello world.”
Listing One: helloworld.cpp
#include <qapplication.h>
#include <qlabel.h>
int main( int argc, char* argv[] )
{
QApplication myapp( argc, argv );
QLabel* mylabel = new QLabel( “Hello world”, 0 );
mylabel->resize( 120, 30 );
myapp.setMainWidget( mylabel );
mylabel->show();
return myapp.exec();
} |
Let’s go through this code line by line. First, we include two of Qt’s header files. In general, there is one header file per Qt class. Since we will want to use both the classes QApplication and QLabel, we include the header files qapplication.h and qlabel.h. When in doubt about necessary header files, check the excellent reference documentation that comes with Qt. It will tell you exactly which header file to include in order to use a certain class. (You can also find the documentation online at http://doc.trolltech.com/.)
Next is the main() function. In this function, we first create a QApplication object on the stack. QApplication is one of the most important classes in Qt; it does all the event handling (more about this later) and ties all the pieces together. You always need exactly one QApplication object in a Qt program; if you do not create one, nothing will happen, and if you create more than one, Qt will complain and the program will terminate.
In the next few lines, we create a QLabel object, give it a certain size, and show it. QLabel is one of many widgets supported by Qt. A widget (”control” in Windows lingo, “component” in Java lingo) is one user interface element. Widgets are often simple items like the labels (which display text), push buttons, menu bars, and so on. New widgets can also be created by combining existing widgets.
Before we go further, it is important to know that Qt widgets should be allocated on the heap (i.e., with the new operator). This also applies to many other Qt objects. This is due to the fact that Qt keeps a hierarchy of its objects, and when an object higher up in the hierarchy is deleted, all its dependent objects will be dynamically deleted as well. But this only happens if the dependent objects were created on the heap. You can still delete the dependent object manually, but you usually do not need to. Keep in mind that creating Qt widgets on the stack (as local variables) can lead to hard-to-debug crashes, so don’t do it.
One more word about labels: We use them here in the simplest possible way — by showing some plain text. Labels are actually much more flexible. They can display stylized text (e.g., with different colors, fonts, etc.), bitmap graphics, vector graphics, and even animation.
Linux Magazine /
December 2001 / FEATURES
Linux GUI Development with QT