GUI Development with Qt

Qt is one of the most popular GUI toolkits in the open source world, and it serves as the foundation of the KDE project. Getting started with it is a snap.

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):


And build Qt:


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.


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 );
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.


<< prev   page 1 2 3 4 5   next >>


Linux Magazine /
December 2001 / FEATURES
Linux GUI Development with QT

The line myapp.setMainWidget( mylabel ); tells Qt that the label widget we have just created is the main widget of the application. This means that if you delete the label via the window manager (i.e., by clicking on the close button that most windows on the screen have), then the whole application will be terminated. If you omitted this line, then clicking on the close button would still close the window of your application, but the process would not terminate — and you would have no way of terminating it yourself without using the kill command.

Finally, in the last line, we call the exec() method of the QApplication class to get the ball rolling. It’s at this point that user interaction events will be processed, and only here will the label actually be shown — calling show() only marked it to be shown.

To see this code in action, though, we must compile it. If your distribution provides packages for Qt development, make sure they’re installed and then set up your environment as follows:

Red Hat:

export QTINC=/usr/lib/qt-2.3.1/include
export QTLIB=/usr/lib/qt-2.3.1/lib

export QTINC=/usr/include/qt
export QTLIB=/usr/lib

If you use neither of these distributions, don’t worry. Just set QTINC to point to where the Qt headers are and set QTLIB to where libqt.so is. (If you’d rather install Qt from source, see the Getting and Installing Qt sidebar.)

Qt Helloworld
Figure One: The syntactic structure of the while command.

Once you’re set up, you can compile your program like:

g++ -I$QTINC -L$QTLIB -lqt -o helloworld helloworld.cpp

Now you should be able to simply start the program with:


The result should look like Figure One.


Congratulations, you have just written and run your first Qt program. The next step is to be able to react to user interaction. Things like the user pressing a button, selecting a menu entry, simply moving the mouse over a window, or pressing a key — these are all actions that your program can react to.

The ways in which user interaction is tied to a function or method in your program differ greatly among the GUI toolkits. Qt employs the so-called signal-and-slot method. The signal-and-slot mechanism makes component-based programming possible. Qt implements a component model that allows programs to dynamically load objects at any point during run-time. Communicating through signals-and-slots lets you write components independently from one another and still be able to bring them together with a few simple lines of code.

Like other Qt objects, Qt components emit “signals” whenever something interesting happens. What is considered interesting depends on the component. For a button, the fact that it has been clicked is certainly interesting.

When something interesting happens, you want your program to react to it, so Qt components also have “slots.” The purpose of a slot is to perform specific actions when a signal occurs. At the source level, slots look a lot like C++ methods. We’ll show you how to define your own slots in a minute, but for now let’s just connect some standard signals and slots. For this, we will introduce a new Qt class named QPushButton. This class implements a simple button and emits a signal that is named clicked() whenever the button is clicked (there are also other signals such as pressed() and released(), but we won’t use them now). The slot we will use is the built-in quit() slot from the QApplication class. See Listing Two for the code.

Listing Two: button.cpp

#include <qapplication.h>
#include <qpushbutton.h>

int main( int argc, char* argv[] )
QApplication myapp( argc, argv );

QPushButton* myquitbutton = new QPushButton( “Quit”, 0 );
myquitbutton->resize( 120, 30 );
QObject::connect( myquitbutton, SIGNAL(clicked()), &myapp, SLOT(quit()) );

myapp.setMainWidget( myquitbutton );
return myapp.exec();


<< prev   page 1 2 3 4 5   next >>


Linux Magazine /
December 2001 / FEATURES
Linux GUI Development with QT

We have mostly just replaced the QLabel with a QPushButton, but the interesting new line is the one that starts with QObject::connect. It connects the clicked() signal of the push button with the quit() slot of the QApplication object. You can probably already guess what this means. When the user clicks the button (aptly labeled “Quit”), the application will terminate. Save this code as button.cpp and compile it:

g++ -I$QTINC -L$QTLIB -lqt -o button button.cpp

Run the program, click the button, and see what happens. We won’t show you a screenshot here, since it does not look very different from the previous program.


In order to define your signals and slots, you need to extend your class declarations. The general pattern is as follows:

class MyComponent : public QWidget

MyComponent( … );

// your signals go here

public slots:
// your public slots go here

// your public non-slot methods go here

… same for protected and private …


There are several things about this pattern that we should note. First, any class that wants to use the signal-and-slot mechanism needs to inherit from the class QObject either directly or indirectly. The code skeleton above inherits from QWidget, which in turns inherits QObject. Next, all classes that want to implement signals and/or slots need to include the macro Q_OBJECT at the beginning of the class declaration.

Slots are just ordinary C++ methods that you have marked up as shown above. This means that you just need to implement them as you usually would in your class implementation. Signals, on the other hand, are implemented internally by Qt. Again, this means that you do not write any signal code yourself.

You might wonder how your C++ compiler is able to understand new keywords like signals and slots. Well, it doesn’t. These pseudo-keywords are dealt with by a preprocessor called the Meta-Object Compiler, or moc. This tool needs to be run on each class declaration that defines signals and/or slots. moc creates another C++ source file that you compile and link (just like your ordinary source files) and is run like:

moc -o moc_mycomponent.cpp mycomponent.h

If you find that you are receiving strange linking errors about undefined signals while writing Qt programs, chances are pretty good that you’ve simply forgotten to run moc and forgotten to compile and link the moc-generated code with your program.


<< prev   page 1 2 3 4 5   next >>


Linux Magazine /
December 2001 / FEATURES
Linux GUI Development with QT


So far, we have only scratched the surface of all of the things that you can do with Qt. Hopefully, this article has piqued your interest in Qt development. If you would like to look a little deeper into Qt, see References for some pointers to more information.

Qt Versions

At the time this article was written, the current stable version of Qt was version 2.3.1, and version 3.0 was in beta testing. Since then, Qt 3.0 has been released, but everything described here will apply to both Qt 2.3.1 as well as Qt 3.0.

Qt 3.0 brings with it a lot of new features that will help you increase the functionality of your programs. These include:

Database Support — Qt 3.0 provides a cross-platform API for accessing SQL databases.

Qt Designer — The GUI builder has been vastly improved, and people used to RAD tools should feel right at home with it.

Qt Linguist — This tool is supposed to make it easier to localize Qt programs. (Translators will especially appreciate this one.)

Qt Assistant — This is a document-browsing tool made especially for browsing Qt-related documentation.

Improved International Text Display — Support for non-Western alphabets has been improved, and character sets may be intermixed within an application. Right-to-left and bi-directional languages (like Hebrew and Arabic) are also supported now.

Improved Regular Expressions — Regular expressions are now Perl-compatible and Unicode-aware.

64bit Safety — The source code has been audited to make sure that everything will behave correctly regardless of whether it was compiled on a 32-bit machine or a 64-bit machine.

More details on Qt 3.0 are available online from Trolltech’s Web site at http://www.trolltech.com/company/announce/30pre.html.


Programming with Qt by Matthias Kalle Dalheimer,ISBN 1-56592-588-2 http://www.oreilly.com/catalog/prowqt

Online Qt Documentation: http://doc.trolltech.com

The Qt Component Model: http://doc.trolltech.com/3.0/component.html

What’s New in Qt 3.0: http://www.trolltech.com/company/announce/30pre.html

Getting GUI with GTK: http://www.linux-mag.com/2001-06/gtK_01.html

GNOME: http://www.gnome.org

KDE: http://www.kde.org

KOffice: http://www.koffice.org

Matthias Kalle Dalheimer is President & CEO of Klarälvdalens Datakonsult AB and a member of the KDE core team. He can be reached at kalle@klaralvdalens-datakonsult.se.


<< prev   page 1 2 3 4 5       


Linux Magazine /
December 2001 / FEATURES
Linux GUI Development with QT

Comments are closed.

 Stick a Fork in Flock: Why it Failed
 CentOS 5.6 Finally Arrives: Is It Suitable for Business Use?
 Rooting a Nook Color: Is it Worth It?
System Administration
 Scripting, Part Two: Looping for Fun and Profit
 Command Line Magic: Scripting, Part One
 Making the Evolutionary Leap from Meerkat to Narwhal
 Extended File Attributes Rock!
 Checksumming Files to Find Bit-Rot
 What's an inode?
 Putting Text to Speech to Work
 Look Who's Talking: Android Edition
 Upgrading Android: A Guided Tour
 A Little (q)bit of Quantum Computing
 Emailing HPC
 Chasing The Number