Sie sind auf Seite 1von 8

Praktikum Computergraphik

– Qt Crash-Kurs –

Wintersemester 2003/2004

Universität Siegen
Fachgruppe Computergraphik & Multimediasysteme
1 Getting Started 2

1 Getting Started

Trolltech’s Qt ist eine C++ Klassenbibliothek, die es ermöglicht auf schnelle und einfache
Weise plattformunabhängige Anwendungen mit ansprechender Benutzeroberfläche (GUI1 ) zu
implementieren. Eine Besonderheit von Qt ist dabei, dass der spezifische GUI-Stil jeder Platt-
form bereitgestellt wird, d.h. ein Qt-Programm unter Windows hat das Look-and-Feel einer
nativen Windows-Anwendung, während der gleiche Quellcode unter Linux beispielsweise den
KDE-typischen Stil annehmen kann.
GUI-basierte Anwendungen unterscheiden sich grundlegend von “herkömmlichen” Program-
men, die Eingabedaten lesen, eine Berechnung ausgeführen und ein Ergebnis ausgegeben. In
einer interaktiven GUI-Anwendung stellt die Applikation beim Start lediglich einen Anfangs-
zustand her. Der Benutzer wählt dann zur Laufzeit Kommandos aus, auf die das Programm
mit entsprechenden Aktionen reagiert. Ein solches Programm-Konzept nennt man Ereignis-
oder Event-basiert. Die interne Programmschleife, in der das Programm auf Benutzereingabe
wartet und darauf reagiert, nennt man Event Loop. Dieser grundlegende Mechanismus wird
bei Qt von einem QApplication-Objekt bereitgestellt.
Ein minimales Qt-Programm ist im folgenden Listing dargestellt:

#include <qapplication.h>
#include <qmainwindow.h>

int main(int argc,char **argv) {

QApplication app(argc,argv);

QMainWindow *win = new QMainWindow();

app.setMainWidget(win);
win->show();

return app.exec();
}

Zunächst wird ein QApplication-Objekt erstellt. Dieses Objekt kann automatisch die Kom-
mandozeilen-Argumente argv und argc parsen und entnimmt dabei entsprechende Qt-rele-
vante Optionen. Für Qt unbekannte Optionen werden zurückgegeben und können wie ge-
habt vom Benutzer ausgewertet werden. Als nächstes wird in diesem Programmbeispiel ein
Hauptfenster (Klasse QMainWindow) generiert. In eigenen Programmen wird hier anstelle des
QMainWindow eine eigene von QMainWindow oder QWidget abgeleitete Klasse verwendet. Dieses
Hauptfenster wird anschließend dem Applikationsobjekt übergeben (setMainWidget(· · · ))
und auf dem Bildschirm angezeigt (show()). Der Aufruf von app.exec() startet schließ-
lich die Event-Loop. Dieser Funktionsaufruf kehrt erst wieder zurück, wenn das Programm
endgültig beendet wird.
1
GUI = Graphical User Interface, Graphische Benutzerschnittstelle
2 GUI-Programmierung 3

Menü

Tool Bar

Drawing Area

Statuszeile

Abbildung 1: Ein typisches Hauptfenster mit Menü, Toolbar, Drawing Area und Statusleiste
wird von Qt durch die Klasse QMainWindow bereitgestellt.

2 GUI-Programmierung

Die graphische Benutzeroberfläche einer typischen Applikation umfaßt üblicherweise ein Menü,
eine Toolbar, eine Statuszeile und eine Drawing Area (Abbildung 1). Dialogboxen enthalten in
der Regel weitere interaktive Elemente wie Buttons, Schieberegler, Scrollbars und dergleichen.
Für jedes dieser Elemente existieren in Qt entsprechende Klassen, die entweder direkt verwen-
det werden oder als Basisklassen für eigene Implementierungen dienen. Alle Klassennamen
der Qt-Bibliothek beginnen mit einem Q und sind daher leicht zu erkennen. Eine vollständige,
dokumentierte Liste der Qt-Klassen ist in der HTML-Hilfe zu finden.
Wer aufwändige Dialogboxen erstellen will, sollte sich unbedingt das Programm designer
anschauen, das von Qt bereitgestellt wird um GUI-Elemente visuell anzuordnen. In dieser
kurzen Qt-Einführung soll auf die Verwendung dieses Tools nicht weiter eingegangen werden.

2.1 signals und slots

Eine Besonderheit bei Qt ist die Art, wie Events, d.h. interne Nachrichten über Benutzerinter-
aktionen gehandhabt werden. Jedes Ereignis, beispielsweise das Drücken einer Taste oder das
Bewegen der Maus sendet ein sogenanntes Signal aus. Als Beispiel zeigt das folgende Listing
einen Teil der Klassendefinition von QButton, einer Klasse die Tasten, Knöpfe und Schalter
repräsentiert.
2.1 signals und slots 4

class QButton : public QWidget {

QButton( ... );
~QButton();

// details omitted

signals:
void pressed();
void released();
void clicked();
void toggled( bool );
void stateChanged( int );

// details omitted
};

Die Klasse QButton sendet beispielsweise ein Signal, wenn die Taste gedrückt wird (pressed),
ein weiteres Signal, wenn sie wieder losgelassen wird (released). Bei Schaltern, sogenannten
Toggle Buttons, sendet die Klasse ein Signal wenn sich der Schaltzustand ändert (toggled
bzw. stateChanged).
Wie man in dem Codefragment sieht, erweitert Qt die C++-Sprachedefinition unter anderem
um das Token signals, das innerhalb einer Klassendefinition die Signale kennzeichnet, die die
Klasse anbietet. Signale können auch zusätzliche Information enthalten, beim toggled-Signal
beispielsweise die Schalterstellung als bool. Signale haben jedoch keinen Rückgabewert.
Das Gegenstück zu einem Signal ist ein sogenannter Slot. Ein Slot ist ein Nachrichten-
empfänger in Form einer Funktion, die immer dann ausgeführt wird, wenn sie ein entsprechen-
des Signal erhält. Das folgende Listing zeigt beispielsweise einen Teil der Klassendefinition
von QSlider, einer Klasse, die für die Implementierung von Schiebereglern verwendet wird.
Das Token slots zeigt an welche Funktionen zur Ereignisbearbeitung die Klasse anbietet. Ge-
nau wie Memberfunktionen können Slots public, protected oder private sein. Die Klasse
QSlider hat einen Slot namens setValue, dem ein Integer-Wert übergeben wird.

Abbildung 2: Der signal-and-slot-Mechanismus von Qt bietet einfache Möglichkeiten GUI-


Elemente miteinander zu verknüpfen, beispielsweise einen Schieberegler (QSlider, links) mit
einem Spin-Button (QSpinBox, rechts).
3 Implementieren eigener Qt-Objekte 5

class QSlider : public QWidget {

public:
QSlider( ... );
~QSlider();

\\details omitted

public slots:
virtual void setValue( int )

\\details omitted
signals:
void valueChanged( int value );
void sliderPressed();
void sliderMoved( int value );
void sliderReleased();
};

Will man nun beispielsweise einen Schieberegler mit einem Spin-Button (Abbildung 2) ver-
knüpfen, so verbindet man jeweils die valueChanged-Signale des einen Elements mit dem
setValue-Slot des anderen:

QSlider sl();
QSpinBox sb();

connect( &sl, SIGNAL(valueChanged(int)), &sb, SLOT(setValue(int)));


connect( &sb, SIGNAL(valueChanged(int)), &sl, SLOT(setValue(int)));

Bewegt man nun den Schieberegler, so wird der Spin-Button automatisch aktualisiert. Verän-
dert man andererseits den Zahlenwert am SpinButton, so wird der Schieberegler automatisch
mitbewegt.
Wie man sieht können auf diese Weise Objekte Nachrichten miteinander austauschen, ohne
übereinander bescheid zu wissen, solange jemand eine Verbindung zwischen den Slots und den
Signalen aufbaut. Dieser Mechanismus ist daher eine sehr praktisches und mächtiges Konzept
für die Entwicklung Event-basierter Anwendungen.

3 Implementieren eigener Qt-Objekte

Um eigene Klassen zu implementieren, die mit dem von Qt angebotenen Signal-and-Slot-


Mechanismus zusammenspielen können, sind einige Dinge zu beachten. Wir erläutern diese
anhand eines Beispiels.
Eine einfache QtKlasse, die intern einen Integer-Wert speichert und für den Zugriff darauf
einen Slot und ein Signal bereitstellt, wird möglicherweise wie folgt aussehen:
3 Implementieren eigener Qt-Objekte 6

class MyClass : public QObject


{
Q_OBJECT
public:
MyClass();
int value() const { return val; }

public slots:
void setValue( int );

signals:
void valueChanged( int );

private:
int val;
};

Diese Klasse kann durch das Signal valueChanged anderen Objekten mitteilen, dass sich ihr
Wert geändert hat. Sie stellt außerdem einen Slot bereit, an den andere Klassen Signale senden
können. Zu beachten ist hierbei nur, dass alle Objekte, die Signale und Slots verwenden, das
Makro Q OBJECT in ihrer Klassendeklaration haben müssen.
Die Slots, d.h. die Funktionen, die aufgerufen werden sollen, wenn ein Signal über den entspre-
chenden Slot empfangen wird, müssen vom Benutzer implementiert werden. Eine mögliche
Implementierung für den setValue Slot wäre:

void MyClass::setValue( int v )


{
if ( v != val ) {
val = v;
emit valueChanged(v);
}
}

Diese Funktion demonstriert auch, wie eine Klasse Signale aussenden kann, in diesem Beispiel
durch
emit valueChanged(v).

Generell werden Signale durch den Aufruf


emit <signal>(<arguments>)
gesendet.
Der Code für Signale wird automatisch durch den Metaobjekt-Compiler (Siehe Abschnitt 4)
generiert. Signale dürfen nicht im Quellcode implementiert werden.
Die Basisklasse der meisten GUI-Elemente in Qt ist die Klasse QWidget. Sie stellt bereits
Event-Handler für Maus- und Tastatur-Events bereit (siehe HTML-Doku zu QWidget). Diese
Funktionen können in einer abgeleiteten Klasse überschrieben und durch eigene Implemen-
tierungen der entsprechenden Event-Handler ersetzt werden.
4 Compilieren und Linken 7

4 Compilieren und Linken

Obwohl Qt die C++-Sprachdefinition um die Tokens signals, slots und emit erweitert,
kann zum Erstellen der Programme jeder beliebige C++-Compiler verwendet werden. Der
Preprocessor ändert bzw. entfernt die Tokens aus dem Quelltext, sodass der C++-Standard
eingehalten wird.
Quellcode, der Qt-Klassen enthält, muss allerdings zusätzlich zum Compilieren auch noch
von einem sogenannten Metaobjekt-Compiler (moc) verarbeitet werden. Dabei hat es sich
als hilfreich erwiesen, alle Quellcode-Dateien, die Qt-Klassen enthalten, zu kennzeichnen,
beispielsweise durch Einfügen von .qt vor der Dateiendungen der Implementierungs- und
Header-Dateien:

MyClass.qt.h
MyClass.qt.C

Der Metaobjekt-Compiler wird für jede Datei mit Klassendefinitionen, die Signale und Slots
enthalten aufgerufen. Der Metaobjekt-Compiler generiert eine neue C++-Quellcode-Datei, die
anschließend ebenfalls kompiliert und zu den anderen Object-Dateien gelinkt werden muss.
Der Aufruf des Metaobjekt-Compilers erfolgt mit folgender Syntax:
moc <input.qt.h> -o <output.moc.C>
Zum Erstellen eines Programms, dessen Quellcode aus den beiden Dateien MyClass.qt.cpp
und MyClass.qt.h besteht sind demnach folgende Schritte notwendig:

1. Aufruf des Metaobjekt-Compilers mit dem Headerfile


moc MyClass.qt.h -o MyClass.moc.C

2. Kompilieren des Quellcodes2 :


g++ -c MyClass.qt.C -o MyClass.qt.o
g++ -c MyClass.moc.C -o MyClass.qt.o

3. Linken der Objekt-Dateien3 :


g++ MyClass.qt.o MyClass.moc.o -o MyProgramm -lqt

5 Weitere Hinweise

Weitere Dokumentationen und Hinweise finden Sie in der HTML-Hilfe zu Qt, unter Linux
üblicherweise unter usr/share/doc/libqt3/. Alternativ finden Sie die Dokumentation online
in der Developer-Section der Trolltech-Website www.trolltech.com zusammen mit weiteren
Hinweise und Dokumentationen.
Bezüglich Fragen und Hinweise an den Autor dieses Dokuments wenden Sie sich bitte an
Christof Rezk-Salama, rezk@fb12.uni-siegen.de.

2
Beispiel-Compiler gcc, Compilerflags wurden der Übersichtlichkeit halber weggelassen.
3
Linkerflags und zusätzliche Bibliotheken wurden der Übersichtlichkeit halber weggelassen.
6 Literatur 8

6 Literatur

Die HTML-Dokumentation zu Qt erwies sich in der Vergangenheit durchaus als ausreichend


um den Umgang mit der Klassenbibliothek erfolgreich zu meistern. Wer dennoch lieber ein
Lehrbuch in der Hand hat, der findet folgende Werke sicherlich hilfreich:

• Olaf Borkner-Delcarlo
GUI- Programmierung mit Qt. Die GUI- Bibliothek mit C++ erfolgreich einsetzen.
Broschiert - 350 Seiten
Juli 2002, Hanser Fachbuchverlag
ISBN: 3446220542

• Helmut Herold
Das QT-Buch. Portable GUI Programmierung unter Linux/UNIX und Windows
Gebundene Ausgabe - 1162 Seiten
Juni 2001, SuSE Press
ISBN: 3934678769

Das könnte Ihnen auch gefallen