The KDE and Qt Libraries

Das KDevelop-Programmierhandbuch: Leitfaden zur C++-Anwendungsentwicklung für das K Desktop Environment (KDE) mit Hilfe der KDevelop-IDE in der Version 1.2
Zurück |  | Vor

# Kapitel 2. The KDE and Qt Libraries

The Norwegian company Troll Tech (\|\|) provides a so-called GUI toolkit, named Qt . Thereby, GUI means "Graphical User Interface", and therefore, Qt -based applications represent themselves with buttons, windows etc, allowing user input by visualizing the functions an application provides. Such a toolkit is needed for developing graphical applications that run on the X-Window interface on Unix Systems, because X does not contain a pre-defined user interface itself. Although other toolkits are also available to create User Interfaces, Qt offers some technical advantages that make application design very easy. Additionally, the Qt toolkit is also available for Microsoft Windows systems, which allows developers to provide their applications for both platforms.

The KDE Team (\|\|) joined together with the goal to make using Unix Systems more friendly, and decided to use the Qt toolkit for the development of a window manager on X-Window, plus a variety of tools included with the KDE packages. The K Desktop Environment therefore contains the window manager kwm, the file manager kfm and the launch panel kpanel as the main components plus a variety of first-class utilities and applications. After KDE was out, a lot of developers turned their eyes towards the new environment and what it has to offer them. The KDE libraries are providing essential methods and classes that make all applications designed with them look similar and consistent, so the user has the great advantage that he only has to get accustomed with an application's specific usage, not with handling dialogs or buttons. Also, KDE programs integrate themselves into the desktop and are able to interact with the file manager via drag'n drop , offer session management and many more, if all features offered by the KDE libraries are used.

Both, the Qt toolkit and the KDE libraries , are implemented in the C++ programming language; therefore applications that make use of these libraries are also mostly written in C++. In the following chapter, we'll make a short trip through the libraries to see what already is provided and how Qt and KDE applications are created in general.

# 2.1. The Qt GUI Toolkit

As said, the Qt library is a toolkit that offers graphical elements that are used for creating GUI applications and are needed for X-Window programming. Additionally, the toolkit offers:

- A complete set of classes and methods ready to use even for non-graphical programming issues,

- A good solution towards user interaction by virtual methods and the signal/slot mechanism,

- A set of predefined GUI-elements, called "widgets", that can be used easily for creating the visible elements

- Additional completely pre-defined dialogs that are often used in applications such as progress and file dialogs.

Therefore knowing the Qt classes is very essential, even if you only want to program KDE-applications. To have an impression on the basic concept how GUI-applications are constructed and compiled, we'll first have a look at a sample Qt -only program; then we'll extend it to a KDE program.

## 2.1.1. The first Qt Application

As usual, programs in C++ have to contain a `main()` function, which is the starting point for application execution. As we want them to be graphically visible in windows and offering user interaction, we first have to know, how they can show themselves to the user. For an example, we'll have a look at the first tutorial included with the Qt Online Reference Documentation and explain the basic execution steps; also why and how the application window appears:

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

     int main( int argc, char **argv )
     {
     QApplication a( argc, argv );

     QPushButton hello( "Hello world!" );
     hello.resize( 100, 30 );

     a.setMainWidget( &&;hello );
     hello.show();
     return a.exec();
     }

This application merely paints a window containing a button with "Hello world" as its text. As for all Qt -based applications, you first have to create an instance of the class `QApplication`, represented by `a`.

Next, the program creates an instance of the class `QPushButton` called `hello`, this will be the button. The constructor of `hello` gets a string as a parameter, which is the contents of the widget visible as the buttons text.

Then the `resize()` method is called on the `hello` button. This changes the default size a widget (which is in this case the QPushButton) has when created to the length of 100 pixels and the height of 30 pixels. Finally, the `setMainWidget()` method is called for `a` and the `show()` method for `hello`. The `QApplication` is finally executed by `a.exec()`, enters the main event loop and waits until it has to return an integer value to the overlaying Operating System signaling that the application is exited.

## 2.1.2. The Reference Documentation for Qt

Now, let's have a quick look at the reference documentation of the Qt library. To do this, start KDevelop and select "Qt -library" from the "Help"-menu in the menubar. The documentation browser opens and shows you the start page of the Qt reference. This will be your first place to get information about Qt , it's classes and the available functions they provide. Also, the above program is the first that is included in the tutorials section. To get to the classes we want to have a look at, `QApplication` and `QPushButton`, select "Alphabetical Class List" and search for the according names. Follow either of them to have a look at the class documentation .

For `QApplication`, you will see the constructor and all other methods that this class provides. If you follow a link, you will get more information about the usage and meaning of the methods, which is very useful when you sometimes can't detect the correct use or want to have an example. This also counts for the KDE library documentation, which uses a similar documentation type; therefore this is almost all you have to know about using the class-references with the documentation browser.

## 2.1.3. Interpretation of the Sample

Starting with `QApplication`, you will find all the methods used in our first example:

- the constructor `QApplication()`,

- the `setMainWidget()` method and

- the `exec()` method.

The interpretation why we use these methods is very simple:

1. first create an instance of the class `QApplication` with the constructor, so we can make use of the GUI elements provided by Qt ,

2. create a widget which will be the contents of our program window,

3. set the widget as the main widget for `a`,

4. execute the `a` instance of `QApplication`.

The second object of our program is the pushbutton, an instance of the class `QPushButton`. From the two constructors given to create an instance, we used the second: this accepts a text, which is the label contents of the button; here, it is the string "Hello world!". Then we called the `resize()` method to change the size of the button according to it's contents- the button has to be larger to make the string completely visible.

But what about the `show()` method ? Now, you see that like most other widgets, `QPushButton` is based on a single-inheritance- here, the documentation says, Inherits `QButton`. Follow the link to the `QButton` class. This shows you a lot of other methodss that are inherited by QPushButton, which we'll use later to explain the signal/slot mechanism. Anyway, the `show()` method is not listed, therefore, it must be a method that is provided by inheritance as well. The class that `QButton` inherits, is `QWidget`. Just follow the link again, and you will see a whole bunch of methods that the `QWidget` class provides; including the `show()` method. Now we understand what was done in the sample with the button:

1. create an instance of `QPushButton`, use the second constructor to set the buttons text,

2. resize the widget to it's contents,

3. set the widget as the main widget of the `QApplication` instance `a`,

4. tell the widget to display itself on the screen by calling `show()`, an inherited method from `QWidget`.

After calling the `exec()` method, the application is visible to the user, showing a window with the button showing "Hello world!". Now, GUI programs behave somewhat differently than procedural applications. The main thing here is that the application enters a so-called "main event loop". This means that the program has to wait for user actions and then react to it, also that for a Qt application, the program has to be in the main event loop to start the event handling. The next section tells you in short what this means to the programmer and what Qt offers to process user events.

(For already advanced users: The button has no parent declared in the constructor, therefore it is a top-level widget alone and runs in a local event loop which doesn't need to wait for the main event loop, see the `QWidget` class documentation and The KDE Library Reference Guide)

Summary:

A Qt application always has to have one instance of the class `QApplication`. This provides that we can create windows that are the graphical representation of programs to the user and allow interaction. The window contents itself is called a "Main Widget", meaning that all graphical elements are based on the class `QWidget` and can be any type of widget that fits the needs of the application to communicate with the user. Therefore, all user elements somehow have to inherit `QWidget` to be visible.

## 2.1.4. User Interaction

After reading the last sections, you should already know:

- What the Qt -library provides in terms of GUI applications,

- how a program using Qt is created and

- where and how to find information about classes that you want to use with the documentation browser

Now we'll turn to give the application "life" by processing user events. Generally, the user has two ways to interact with a program: the mouse and the keyboard. For both ways, a graphical user interface has to provide methods that detect actions and methods that do something as a reaction to these actions.

The Window system therefore sends all interaction events to the according application. The QApplication then sends them to the active window as a `QEvent` and the widgets themselves have to decide what to do with them. A widget receives the event and processes `QWidget`::event(QEvent*)/, which then decides which event has been executed and how to react; event() is therefore the main event handler. Then, the `event()` function passes the event to so-called event filters, that determine what happened and what to do with the event. If no filter signs responsible for the event, the specialized event handlers are called. Thereby we can decide between:

a) Keyboard events --TAB and Shift-TAB keys:

changes the keyboard input focus from the current widget to the next widget in the focus order. The focus can be set to widgets by calling `setFocusPolicy()` and process the following event handlers:

- `virtual void focusInEvent ( QFocusEvent * )`

- `virtual void focusOutEvent ( QFocusEvent * )`

b) all other keyboard input:

- `virtual void keyPressEvent ( QKeyEvent * )`

- `virtual void keyReleaseEvent ( QKeyEvent * )`

c) mouse movements:

- `virtual void mouseMoveEvent ( QMouseEvent * )`

- `virtual void enterEvent ( QEvent * )`

- `virtual void leaveEvent ( QEvent * )`

d) mouse button actions:

- `virtual void mousePressEvent ( QMouseEvent * )`

- `virtual void mouseReleaseEvent ( QMouseEvent * )`

- `virtual void mouseDoubleClickEvent ( QMouseEvent * )`

e) window events containing the widget:

- `virtual void moveEvent ( QMoveEvent * )`

- `virtual void resizeEvent ( QResizeEvent * )`

- `virtual void closeEvent ( QCloseEvent * )`

Note that all event functions are virtual and protected; therefore you can re-implement the events that you need in your own widgets and specify how your widget has to react. `QWidget` also contains some other virtual methods that can be useful in your programs; anyway, it is sufficient to know about `QWidget` very well generally.

## 2.1.5. Object Interaction by Signals and Slots

Now we're coming to the most obvious advantages of the Qt toolkit: the signal/slot mechanism. This offers a very handy and useful solution to object interaction, which usually is solved by `callback` functions for X-Window toolkits. As this communication requires a strict programming and sometimes makes user interface creation very difficult (as referred by the Qt documentation and explained in Programming with Qt by K.Dalheimer), Troll Tech invented a new system where objects can emit signals that can be connected to methods declared as slots. For the C++ part of the programmer, he only has to know some things about this mechanism:

1. the class declaration of a class using signals/slots has to contain the `Q&_;OBJECT` macro at the beginning (without the semicolon); and have to be derived from the `QObject` class,

2. a signal can be emitted by the keyword `emit`, e.g. `emit signal(parameters);` from within any member function of a class that allows signals/slots,

3. all signals used by the classes that are not inherited have to be added to the class declaration by a `signals:` section,

4. all methods that can be connected with a signal are declared in sections with the additional keyword `slot`, e.g. `public slots:` within the class declaration,

5. the meta-object compiler `moc` has to run over the header file to expand the macros and to produce the implementation (which is not needed to know.). The output files of `moc` are compiled as well by the C++ compiler.

Another way to use signals without deriving from `QObject` is to use the `QSignal` class- see the reference documentation for more information and example usage. In the following, we assume you're deriving from `QObject`.

This way, your class is able to send signals anywhere and to provide slots that signals can connect to. By using the signals, you don't have to care about who's receiving it- you just have to emit the signal and whatever slot you want to connect to it can react to the emission. Also the slots can be used as normal methods during implementation.

Now, to connect a signal to a slot, you have to use the `connect()` methods that are provided by `QObject` or, where available, special methods that objects provide to set the connection for a certain signal.

### 2.1.5.1. Sample Usage

To explain the way how to set up object-interaction, we'll take our first example again and extend it by a simple connection:

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

     int main( int argc, char **argv )
     {
     QApplication a( argc, argv );

     QPushButton hello( "Hello world!" );
     hello.resize( 100, 30 );

     a.setMainWidget( &&;hello );

     connect(&&;hello, SIGNAL( clicked() ), &&;a, SLOT( quit() ));

     hello.show();
     return a.exec();
     }

You see, the only addition to give the button more interaction is to use a `connect()` method: `connect(&&;hello, SIGNAL( clicked() ), &&;a, SLOT( quit() ));` is all you have to add. What is the meaning now ? The class declaration of `QObject` says about the `connect()` method:

`bool connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * member )`

This means, you have to specify a QObject instance pointer that is the sender of the signal, meaning that it can emit this signal as first parameter; then you have to specify the signal that you want to connect to. The last two parameters are the receiver object that provides a slot, followed by the member function which actually is the slot that will be executed on signal emission.

By using signals and slots, your program's objects can interact with each other easily without explicitely depending on the type of the receiver object. You will learn more about using this mechanism for productive usage later in this handbook. More information about the Signals/Slot mechanism can also be found in The KDE Library Reference Guide and the Qt online reference.

Zurück | Anfang | Vor
Additional Information |  | What KDE provides