Kapitel 1. Übersicht über die Qt-Klassenhierarchie

Wenn Sie ein Gebiet kennenlernen möchten,
müssen Sie zuerst die Karte studieren.

— Tony Buzan

Das erste Qt-Programm

Um das erste Qt-Programm zu schreiben und auszuführen, müssen Sie zunächst die Qt-Bibliothek selbst und alle erforderlichen Komponenten installieren. Falls Sie dies noch nicht getan haben, finden Sie eine Anleitung dazu in Anhang 1 dieses Buches.

Nun ist alles für die Arbeit vorbereitet! Das bedeutet, dass es – wie bei jeder ersten Begegnung üblich – Zeit ist, sich vorzustellen. Und um niemanden auszulassen, wenden wir uns gleich an die ganze Welt. Schreiben wir dazu ein kurzes Programm „Hello, World!” („Hallo, Welt!“), dessen Ausführungsergebnis in Abb. 1.1 dargestellt ist.

Qt Hello World Programm Fenster mit Begrüßungstext
Abb. 1.1. Das Programmfenster „Hello, World!”

Das Schreiben solcher Programme ist bereits zur Tradition geworden, wenn man eine neue Sprache oder Bibliothek kennenlernt. Obwohl ein solches Beispiel nicht das gesamte Potenzial und alle Möglichkeiten der Bibliothek demonstrieren kann, vermittelt es ein Verständnis der grundlegenden Konzepte und ermöglicht eine Einschätzung des Umfangs und der Komplexität der Programmimplementierung mit der jeweiligen Bibliothek. Außerdem kann man anhand dieses Beispiels überprüfen, ob alles für die Kompilierung und das Linking korrekt installiert wurde.

Listing 1.1. Programm „Hello, World!” (Datei hello.cpp)

#include <QtWidgets>

int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    QLabel lbl("Hello, World !");
    lbl.show();
    return app.exec();
}

In der ersten Zeile von Listing 1.1 wird die aggregierte Header-Datei QtWidgets eingebunden, die ein Modul darstellt und die Header-Dateien für die in unserem Programm verwendeten Klassen QApplication und QLabel enthält. Dies macht das Beispiel kompakt und leicht lesbar. In Lernbeispielen und kleinen Demonstrationen ist diese Einbindung gerechtfertigt – der Code wird kürzer und leichter verständlich. Bei der Entwicklung realer, großer Projekte ist jedoch die explizite Einbindung nur der benötigten Header-Dateien vorzuziehen. Explizite Einbindungen reduzieren die an den Compiler übertragene Datenmenge und helfen, Abhängigkeiten präziser zu verfolgen.

Dateiarchiv

Das Dateiarchiv mit den Beispielen zu diesem Buch können Sie unter folgendem Link herunterladen: https://qt-book.com/examples/Max_Schlee-Qt_6_9_Book-Examples.zip (siehe Anhang 4). Die in den Listing-Bezeichnungen genannten Dateien befinden sich in Ordnern mit den entsprechenden Kapitelnummern.

Betrachten wir nun unser Beispiel genauer. Zunächst wird ein Objekt der Klasse QApplication erstellt, das die Anwendungssteuerung übernimmt. Für dessen Erstellung müssen dem Konstruktor dieser Klasse zwei Argumente übergeben werden. Das erste Argument enthält die Anzahl der Kommandozeilenargumente, mit denen das Programm aufgerufen wurde, und das zweite ist ein Zeiger auf ein Array von Zeichenketten, die die Argumente enthalten, jeweils eine pro Zeile. Jedes Qt-Programm mit grafischer Benutzeroberfläche muss genau ein Objekt dieser Klasse erstellen, und es muss vor der Verwendung von Benutzeroberflächenoperationen erstellt werden.

Anschließend wird ein Objekt der Klasse QLabel erstellt. Nach der Erstellung sind Qt-Steuerelemente standardmäßig unsichtbar, und zur Anzeige muss die Methode show() aufgerufen werden. Das Objekt der Klasse QLabel ist das Hauptsteuerelement der Anwendung, was es ermöglicht, die Anwendung beim Schließen des Elementfensters zu beenden. Wenn sich herausstellt, dass die erstellte Anwendung mehrere voneinander unabhängige Steuerelemente enthält, wird beim Schließen des Fensters des letzten Steuerelements auch die Anwendung selbst beendet. Dies ist korrekt, da die Anwendung sonst im Arbeitsspeicher verbleiben und Ressourcen verbrauchen würde.

Schließlich wird in der letzten Programmzeile die Anwendung durch den Aufruf von QApplication::exec() gestartet. Mit diesem Start wird die in der Klasse QCoreApplication definierte Ereignisschleife aktiviert, die die Basisklasse für QGuiApplication ist, von der wiederum die Klasse QApplication abgeleitet ist. Diese Schleife leitet die vom System empfangenen Ereignisse zur Verarbeitung an die entsprechenden Objekte weiter. Sie läuft so lange, bis entweder die statische Methode QCoreApplication::exit() aufgerufen wird oder das Fenster des letzten Steuerelements geschlossen wird. Nach Beendigung der Anwendung gibt die Methode QApplication::exec() einen Ganzzahlwert zurück, der den Beendigungscode enthält.

Qt-Module

Bei Programmierern, die mit dem Erlernen von Klassen einer neuen Bibliothek beginnen, entsteht aufgrund der großen Informationsmenge, die aufgenommen werden muss, oft ein Gefühl der Übersättigung. Doch die Qt-Klassenhierarchie hat eine klare innere Struktur, die es wichtig ist, sofort zu verstehen, um später gut und intuitiv in dieser Bibliothek navigieren zu können.

Die Qt-Bibliothek besteht aus einer Vielzahl von Klassen (etwa 1.800), die einen Großteil der Funktionalitäten der Betriebssysteme abdecken und dem Entwickler leistungsstarke Mechanismen zur Verfügung stellen, die die Anwendungsentwicklung erweitern und zugleich vereinfachen — ohne dabei die Philosophie des jeweiligen Betriebssystems zu verletzen. Qt ist kein monolithisches Ganzes; es ist in Module unterteilt, die eine logische Abhängigkeitsstruktur bilden (Tab. 1.1).

Tabelle 1.1. Einige Qt-Module

Bibliothek Bezeichnung in der Projektdatei (qmake / CMake) Zweck
QtCore core / Qt6::Core Grundlegendes Modul, bestehend aus Klassen ohne Bezug zur grafischen Benutzeroberfläche (siehe Teile I, IV)
QtGui Gui / Qt6::Gui Basisklassen für die Programmierung grafischer Benutzeroberflächen
QtWidgets widgets / Qt6::Widgets Erweitert QtGui um „Baumaterial” für grafische Benutzeroberflächen in Form von C++-Widgets (siehe Teile II, III, IV, V)
QtQuick quick / Qt6::Quick Deklaratives Framework für die schnelle Entwicklung von Benutzeroberflächen der nächsten Generation (siehe Teil VIII)
QtQML qml / Qt6::Qml Engine für die Sprachen QML und JavaScript (siehe Teil VIII)
QtNetwork network / Qt6::Network Modul für die Programmierung von TCP-, UDP-, HTTP- und FTP-Verbindungen (siehe Kapitel 39)
QtSql sql / Qt6::Sql Modul für Datenbankprogrammierung (siehe Kapitel 41)
QtSvg svg / Qt6::Svg Modul für die Arbeit mit SVG (Scalable Vector Graphics) (siehe Kapitel 22)
QtXml xml / Qt6::Xml Modul zur XML-Unterstützung mit SAX- und DOM-Schnittstellen (siehe Kapitel 40)
QtHttpServer httpserver Modul zur Erstellung von HTTP-Servern (siehe Kapitel 39)
QtMultimedia multimedia / Qt6::Multimedia Multimedia-Modul: Unterstützung für Audio, Video, Kamera und Radio (siehe Kapitel 27)
QtMultimediaWidgets multimediawidgets / Qt6::MultimediaWidgets Widget-basierte UI-Komponenten für QtMultimedia (siehe Kapitel 27)
QPrintSupport printsupport / Qt6::PrintSupport Modul zur Druckerunterstützung (siehe Kapitel 24)
QtTest test / Qt6::Test Framework für Unit-Tests (siehe Kapitel 45)
QtConcurrent concurrent High-Level-API für Multithreading-Programmierung (siehe Kapitel 38)

Jedes Qt-Programm verwendet mindestens die drei Module aus Listing 1.1 — QtCore, QtGui und QtWidgets —, die in jeder GUI-Anwendung vorhanden sind und daher standardmäßig vom Build-System-Generator eingebunden werden (siehe Kapitel 3). Qt 6 unterstützt zwei Build-Werkzeuge: qmake und CMake. Beide werden ausführlich in Kapitel 3 behandelt; hier zunächst eine kurze Demonstration. Wenn Ihre Anwendung beispielsweise zusätzliche Funktionen benötigt, können Sie die erforderlichen Module zur Projektdatei hinzufügen:

QT += widgets network sql

Um ein Modul aus dem Projekt auszuschließen:

QT -= gui

Bei CMake-basierten Projekten werden die Module im Aufruf von find_package (großgeschrieben) angegeben und anschließend mit Ihrem Ziel verlinkt:

find_package(Qt6 REQUIRED COMPONENTS Widgets Network Sql)
target_link_libraries(<your_target> PRIVATE Qt6::Widgets Qt6::Network Qt6::Sql)

wobei <your_target> der Name Ihres Build-Ziels ist.

Es sei außerdem erwähnt, dass CMake in Qt 6 das bevorzugte Build-Werkzeug ist.

Das wichtigste der in Tabelle 1.1 aufgeführten Module ist QtCore, da es die Grundlage für alle anderen Module bildet. Direkt von QtCore abhängig sind die Module: QtNetwork, QtGui, QtSql und QtXml.

Für jedes Modul stellt Qt eine einzelne aggregierte Header-Datei bereit, die die Header-Dateien aller Klassen dieses Moduls enthält. Der Name dieser Header-Datei entspricht dem Modulnamen. Um beispielsweise das Modul QtWidgets einzubinden, fügen Sie Ihrem Programm folgende Zeile hinzu, wie wir es bereits in Listing 1.1 getan haben:

#include <QtWidgets>

Der Qt-Namensraum

Der Namensraum Qt enthält eine Reihe von Aufzählungstypen und Konstanten, die häufig in der Qt-Programmierung verwendet werden. Um auf eine Konstante dieses Namensraums zuzugreifen, müssen Sie ihr das Präfix Qt voranstellen (verwenden Sie also z. B. Qt::red statt red). Wenn Sie das Präfix Qt weglassen möchten, fügen Sie am Anfang Ihrer Quellcodedatei folgende Direktive hinzu:

using namespace Qt;

Das Modul QtCore

QtCore ist das grundlegende Modul. Es liegt allen Qt-Anwendungen zugrunde und enthält keine Klassen für die Benutzeroberfläche. Wenn Sie eine Konsolenanwendung entwickeln, genügt Ihnen möglicherweise dieses eine Modul. QtCore umfasst mehr als 250 Klassen, darunter:

  • Container-Klassen: QList, QMap, QVariant, QString usw. (siehe Kapitel 4);
  • Klassen für Ein- und Ausgabe: QIODevice, QTextStream, QFile (siehe Kapitel 36);
  • Die Prozessklasse QProcess sowie Klassen für Multithreading: QThread, QWaitCondition, QMutex, QSemaphore (siehe Kapitel 38);
  • Timer-Klassen: QBasicTimer und QTimer (siehe Kapitel 37);
  • Klassen für Datum und Uhrzeit: QDate, QTime, QDateTime (siehe Kapitel 37);
  • Die Klasse QObject — der Grundstein des Qt-Objektmodells (siehe Kapitel 2);
  • Die Basisklasse für Ereignisse QEvent (siehe Kapitel 14);
  • Die Klasse für Anwendungseinstellungen QSettings (siehe Kapitel 28);
  • Die Anwendungsklasse QCoreApplication, deren Instanz bei Bedarf eine Ereignisschleife ausführen kann;
  • Klassen zur Animationsunterstützung: QAbstractAnimation, QVariantAnimation usw. (siehe Kapitel 22);
  • Klassen für Zustandsautomaten: QStateMachine, QState usw. (siehe Kapitel 22);
  • Klassen für Datenmodelle: QAbstractItemModel, QStringListModel, QAbstractProxyModel (siehe Kapitel 12);
  • JSON-Klassen: QJsonDocument, QJsonObject, QJsonArray, QJsonValue (siehe Kapitel 40);
  • Klassen für reguläre Ausdrücke: QRegularExpression, QRegularExpressionMatch (siehe Kapitel 4).

Das Modul enthält außerdem Unterstützungsmechanismen für Ressourcendateien (siehe Kapitel 3).

Betrachten wir die Klasse QCoreApplication genauer. Das Anwendungsobjekt QCoreApplication lässt sich als ein Gefäß beschreiben, das Objekte enthält, die mit dem Kontext des Betriebssystems verbunden sind. Die Lebensdauer eines QCoreApplication-Objekts entspricht der Laufzeit der gesamten Anwendung und bleibt während der gesamten Programmausführung zugänglich. Ein QCoreApplication-Objekt darf pro Anwendung genau einmal erstellt werden. Zu seinen Aufgaben zählen:

  • Verwaltung von Ereignissen zwischen der Anwendung und dem Betriebssystem;
  • Weiterleitung und Bereitstellung von Kommandozeilenargumenten;
  • Verwaltung des Anwendungslebenszyklus.

Darüber hinaus kann QCoreApplication abgeleitet werden, um bestimmte Methoden zu überschreiben, und ihre Instanz kann als Container für zusätzliche globale Daten der Anwendung dienen. Auf diese Weise lässt sich der unerwünschte Einsatz des Singleton-Entwurfsmusters vermeiden.

Das Modul QtGui

Dieses Modul stellt Klassen für die Integration mit dem Fenstersystem, mit OpenGL und mit Vulkan bereit. Es enthält die Klasse QWindow, die eine elementare Oberfläche darstellt, die Benutzereingabeereignisse, Fokus- und Größenänderungen empfangen kann und zudem Zeichen- und Grafikoperationen auf ihrer Oberfläche unterstützt.

Die Anwendungsklasse dieses Moduls ist QGuiApplication. Sie stellt eine Ereignisschleife bereit und unterstützt zusätzlich:

  • Zugriff auf die Zwischenablage (siehe Kapitel 29);
  • Initialisierung anwendungsweiter Einstellungen — etwa der Farbpalette für Steuerelemente (siehe Kapitel 13);
  • Verwaltung der Mauszeigerform.

Das Modul QtWidgets

Dieses Modul enthält etwa 350 Widget-Klassen, die als Bausteine für die GUI-Programmierung dienen. Einige Highlights:

  • Die Klasse QWidget — die Basisklasse für alle Qt-Steuerelemente. Optisch ist sie nichts weiter als ein gefülltes Rechteck, doch hinter dieser Einfachheit verbirgt sich ein umfangreicher Satz nicht trivialer Fähigkeiten. Die Klasse umfasst etwa 300 Methoden und mehr als 60 Eigenschaften. Sie wird ausführlich in Kapitel 5 behandelt;
  • Layout-Klassen: QVBoxLayout, QHBoxLayout, QGridLayout (siehe Kapitel 6);
  • Klassen für Anzeigeelemente: QLabel, QLCDNumber (siehe Kapitel 7);
  • Schaltflächenklassen: QPushButton, QCheckBox, QRadioButton (siehe Kapitel 8);
  • Klassen für Bereichsregler: QSlider, QScrollBar (siehe Kapitel 9);
  • Eingabeklassen: QLineEdit, QSpinBox (siehe Kapitel 10);
  • Auswahlklassen: QComboBox, QToolBox (siehe Kapitel 11);
  • Menüklassen: QMainWindow und QMenu (siehe Kapitel 31 und 34);
  • Klassen für Meldungsfenster und Dialoge: QMessageBox, QDialog (siehe Kapitel 32);
  • Zeichenklassen: QPainter, QBrush, QPen, QColor (siehe Kapitel 18);
  • Klassen für Rasterbilder: QImage, QPixmap (siehe Kapitel 19);
  • Stilklassen (siehe Kapitel 26) — sowohl einzelnen Steuerelementen als auch der gesamten Anwendung kann ein Stil zugewiesen werden, der ihr Erscheinungsbild ändert;
  • Die Anwendungsklasse QApplication, die die Ereignisschleife bereitstellt.

Betrachten wir den letzten Punkt genauer — die Klasse QApplication, der wir bereits im allerersten Beispiel begegnet sind. Alles zuvor über QCoreApplication Gesagte gilt gleichermaßen für QApplication, da diese von jener abgeleitet ist. Ein QApplication-Objekt dient als zentrale Steuerungsstelle für Qt-Anwendungen mit Widget-basierter Benutzeroberfläche. Dieses Objekt ist dafür zuständig, Tastatur-, Maus-, Timer- und andere Ereignisse zu empfangen, auf die die Anwendung angemessen reagieren muss. So kann beispielsweise selbst das einfachste Anwendungsfenster in der Größe verändert oder von einem Fenster einer anderen Anwendung verdeckt werden, und all diese Ereignisse erfordern eine korrekte Reaktion.

QApplication erbt direkt von QGuiApplication und erweitert es um folgende Fähigkeiten:

  • Verwaltung des Anwendungsstils. Damit lässt sich das Look & Feel der Anwendung festlegen, einschließlich eigener benutzerdefinierter Stile (siehe Kapitel 26);
  • Abrufen eines Zeigers auf das Desktop-Objekt;
  • Verwaltung des globalen Mausverhaltens (etwa des Doppelklick-Intervalls) sowie Erfassung von Mausbewegungen innerhalb und außerhalb des Anwendungsfensters;
  • Sicherstellung eines korrekten Beendens der Anwendung beim Herunterfahren des Betriebssystems (siehe Kapitel 28).

Manchmal ist eine Anwendung inaktiv, obwohl sie die Aufmerksamkeit des Benutzers benötigt. Dafür stellt die Klasse QApplication die statische Methode alert() bereit. Ihr Aufruf bewirkt, dass das Anwendungssymbol im Dock unter macOS hüpft (Abb. 1.2) und in der Taskleiste unter Windows pulsiert (Abb. 1.3).

Hüpfendes Qt-Anwendungssymbol im macOS-Dock nach QApplication::alert()
Abb. 1.2. Hüpfendes Anwendungssymbol im macOS-Dock
Pulsierendes Qt-Anwendungssymbol in der Windows-Taskleiste nach QApplication::alert()
Abb. 1.3. Pulsierendes Anwendungssymbol in der Windows-Taskleiste

Die Module QtQuick und QtQML

Diese bilden eine Alternative zu Widgets — eine Reihe von Technologien für die schnelle Entwicklung grafischer Benutzeroberflächen der nächsten Generation, basierend auf der deklarativen Sprache QML, der Programmiersprache JavaScript und den vollen Fähigkeiten der Qt-Bibliothek (siehe Kapitel 53).

Das Modul QtNetwork

Das Modul QtNetwork stellt Werkzeuge für die TCP- und UDP-Socket-Programmierung bereit (Klassen QTcpSocket und QUdpSocket) sowie für Client-Anwendungen, die die Protokolle HTTP und FTP verwenden (Klasse QNetworkAccessManager). Dieses Modul wird in Kapitel 39 behandelt.

Das Modul QtXml

Das Modul QtXml ist für die Arbeit mit grundlegenden XML-Funktionen über die von Qt definierten SAX2- und DOM-Schnittstellen gedacht (siehe Kapitel 40).

Das Modul QtSql

Dieses Modul ist für die Datenbankprogrammierung gedacht. Es enthält Klassen, die die Bearbeitung von Datenbankwerten ermöglichen (siehe Kapitel 41).

Die Module QtMultimedia und QtMultimediaWidgets

Das Modul QtMultimedia stellt alles bereit, was für die Entwicklung multimediafähiger Anwendungen benötigt wird. Es unterstützt sowohl den Low-Level-Zugriff für feingranulare, spezialisierte Implementierungen als auch eine High-Level-API, mit der sich Audio- und Videowiedergabe mit wenigen Zeilen Code realisieren lässt. Das Modul QtMultimediaWidgets stellt fertige, Widget-basierte Komponenten bereit, die Implementierungszeit sparen. Beide Module werden ausführlich in Kapitel 27 behandelt.

Das Modul QtSvg

Dieses Modul fügt Unterstützung für das auf XML basierende Vektorgrafikformat SVG hinzu. Das Format unterstützt nicht nur die statische Darstellung von Vektorgrafiken, sondern kann auch für Vektoranimationen verwendet werden (siehe Kapitel 22).

Weitere Qt-Module

Neben den wesentlichen Modulen bietet Qt auch optionale Zusatzmodule an, die sich an einen kleineren Kreis von Entwicklern richten (Tab. 1.2). Einige dieser Module müssen bei der Installation explizit über das Qt-Wartungsprogramm (MaintenanceTool) ausgewählt werden.

Tabelle 1.2. Einige zusätzliche Qt-Module

Bibliothek Bezeichnung in der Projektdatei (qmake / CMake) Zweck
QtWebEngineCore webenginecore / Qt6::WebEngineCore Ermöglicht die nahtlose Integration von Web-Inhalten in eine Anwendung
QtWebEngineWidgets webenginewidgets / Qt6::WebEngineWidgets Stellt fertige, Widget-basierte Web-Komponenten bereit und erlaubt die Erweiterung von Web-Inhalten durch eigene Widgets (siehe Kapitel 46)
Qt 3D 3dcore, 3drenderer, 3dinput, 3dlogic, 3dextras, 3danimation, 3dquickscene2d / Qt6::3DCore usw. Eine Sammlung von 7 Modulen: Qt3DAnimation, Qt3DCore, Qt3DExtras, Qt3DInput, Qt3DLogic, Qt3DRender und Qt3DScene2D. Ihr Ziel ist es, die 3D-Grafikprogrammierung zu vereinfachen
QtBluetooth Bluetooth / Qt6::Bluetooth Klassen für die drahtlose Bluetooth-Kommunikation
QtLocation Location / Qt6::Location Geolokalisierungsklassen zur Bestimmung des aktuellen Standorts eines Geräts
QtSensors Sensors / Qt6::Sensors Zugriff auf Sensoren mobiler Geräte wie den Orientierungssensor und den Beschleunigungsmesser. Derzeit werden iOS und Android unterstützt
QtCharts Charts / Qt6::Charts Darstellung von Daten als stilvolle Diagramme unterschiedlicher Komplexität und Typen
QtDataVisualization Datavisualization / Qt6::DataVisualization Darstellung von Daten als 3D-Diagramme
QtRemoteObjects Remoteobjects / Qt6::RemoteObjects Unterstützung für Interprozesskommunikation (IPC). Bietet einen unkomplizierten Mechanismus zum Datenaustausch zwischen Anwendungen auf demselben oder auf entfernten Rechnern
QtCore5Compat core5compat / Qt6::Core5Compat Kompatibilitätsmodul für veraltete Qt-5-APIs: enthält Klassen und Funktionen, die in Qt 6 fehlen, für die Migration älterer Projekte (siehe Kapitel 48)

Zusammenfassung

Die Qt-Bibliothek ist nicht monolithisch — sie ist in einzelne Module unterteilt: QtCore, QtGui, QtWidgets, QtQuick, QtQML, QtMultimedia, QtNetwork, QtSql, QtXml, QtSvg und viele weitere. Jedes Modul hat einen bestimmten Zweck — etwa UI-Programmierung, Grafik, Datenbankzugriff und so weiter. Die Klassen der einzelnen Module stellen Entwicklern leistungsstarke Mechanismen zur Verfügung, die ihre Möglichkeiten erweitern und zugleich die Anwendungsentwicklung vereinfachen. An der Spitze der Modulhierarchie steht QtCore, das Konsolenanwendungen (ohne grafische Benutzeroberfläche) ermöglicht. Ein QCoreApplication-Objekt darf pro Anwendung nur einmal erstellt werden.

Für Anwendungen mit grafischer Benutzeroberfläche wird entweder das Modul QtWidgets oder QtQuick benötigt. Die Klassen QGuiApplication und QApplication bilden das Rückgrat der Qt-GUI-Anwendungen. Eine Instanz einer dieser Klassen darf pro Anwendung nicht mehr als einmal erstellt werden. Qt bietet außerdem zusätzliche optionale Module, die nach Bedarf des Entwicklers installiert werden können.


Entfalten Sie das volle Potenzial dieses Kapitels! Nutzen Sie die zu diesem Kapitel bereitgestellten Zusatzmaterialien, stellen Sie eine Frage, teilen Sie Ihre Erfahrungen oder nehmen Sie an der Diskussion teil unter: https://qt-book.com/01-69-de/

Leave a Reply

Your email address will not be published. Required fields are marked *