Programmentwicklung mit Qt auf Windows 7

Seite 2: Signale, Slots und Diashow

Inhaltsverzeichnis

Auch wenn sich ein File-Browser einfach per statischer Funktion aus der QFileDialog-Klasse aufrufen lässt, ist man doch ohne eigene Klassen recht eingeschränkt. QSimpleViewer erweitert daher unseren Bildbetrachter um die Klassen Gui für die Programmoberfläche, Data für die Bilddaten und View zum Anzeigen des Bildes (alle Dateien hier zum Download). Um die für Echtzeitszenarien wichtige Klasse QTimer zu demonstrieren, ist in dem Programm eine einfache Diashow umgesetzt.

Zunächst sei die Klasse Gui betrachtet, die von QWidget, der Basisklasse aller Widgets, abgeleitet ist. Der Konstruktor generiert die Programmoberfläche mit einem View-Widget, das mit Scroll-Leisten ausgestattet ist. Hier ist ein wichtiges Konzept von Qt zu erkennen: Widgets erscheinen bei Qt in der Regel nur auf dem Bildschirm, wenn sie mit einem Layout-Objekt assoziiert sind. Im Beispiel dient dazu ein QVBoxLayout-Objekt, in das der Aufruf addWidget(scroll) das mit der Scroll-Leiste verzierte View-Widget platziert.

Für den Vollbild-Modus empfiehlt es sich, ein weiteres View-Widget als rahmenloses Fenster zu erzeugen. Das Window-Flag Qt::Window signalisiert, dass ein Toplevel-Fenster erzeugt werden soll, während Qt::FramelessWindowHint den Rahmen verschwinden lässt.

Eines der fundamentalen Konzepte von Qt ist die Verknüpfung von Events mit entsprechenden Handler-Funktionen anhand von Signalen und Slots. Die Signale werden einfach in den Header-Dateien unter dem Schlüsselwort signals: deklariert und mit dem Befehl emit an beliebiger Stelle innerhalb des Programmcodes der Klasse ausgelöst. Die Handler-Funktionen deklariert man in der Header-Datei unter dem Schlüsselwort slots:. Verwendet der Entwickler eines der Schlüsselwörter, muss er das Makro Q_OBJECT in der Header-Datei aufrufen. Zum Verbinden von Signalen und Slots dient die statische Funktion connect aus der Basisklasse QObject.

Der Konstruktor der Gui-Klasse verbindet über QObject::connect die beiden Buttons mit den entsprechenden Funktionen. Das Verlassen des Vollbild-Modus geschieht per Esc-Taste in der View-Klasse. Hier propagiert ein eigenes Signal leaveFullScreen das Event in die Gui-Klasse, wo dann die Funktion normalScreen() die benötigten Einstellungen setzt.

Eine Klasse mit vielfältigen Einsatzmöglichkeiten ist QTimer. Solange das Timing nicht allzu exakt sein muss, lässt sie sich für Echtzeitanwendungen verwenden, um beispielsweise eine Funktion in regelmäßigen Abständen auszuführen. Das Beispiel verwendet QTimer für das Laden des nächsten Bilds in der Diashow. Dazu erzeugt der Konstruktor von Gui ein QTimer-Objekt, setzt das Timer-Intervall auf 3000 ms und verbindet per QObject::connect das Signal timeout() mit der Slot-Funktion nextSlide(). Nun sei ein Blick auf einige der übrigen Funktionen der Klasse Gui geworfen. Die Slot-Funktion loadImages() ruft die statische Funktion QFileDialog::getOpenFileNames() auf, die ein Dialogfenster erzeugt, in dem man die zu ladenden Bilddateien auswählt. Die Funktion Gui::saveImage() verwendet eine statische Funktion der Klasse QFileDialog zur Eingabe eines einzelnen Dateinamens.

Solange diese statischen Funktionen verwendet werden, greift Qt auf die File-Dialoge des jeweiligen Betriebssystems zurück. Unter Windows 7 erscheinen also die Standarddialoge mit entsprechender Lokalisierung. Das ist nicht der Fall, wenn man QFileDialog-Objekte erzeugt und mit der Funktion exec() ausführt.

Zunächst maximiert die Funktion Gui::fullScreen() das im Konstruktor rahmenlos erzeugte fullView-Toplevel-Fenster. Der Aufruf von raise() holt es in den Vordergrund, sodass es vor allen anderen Fenstern steht. Nun ist noch sicherzustellen, dass das Fenster auf Tastatureingaben reagiert, damit man den Vollbild-Modus per Esc-Taste verlassen kann. Mit setFocusPolicy(Qt::StrongFocus) legt der Entwickler fest, dass sich der Fokus sowohl per Maus als auch per Tabulator-Taste selektieren lässt. Zusätzlich kann man den Fokus explizit mit setFocus() setzen. Die Slot-Funktion normalScreen() versteckt das Vollbild-Fenster, sodass wieder das Hauptfenster des Programms erscheint.

Die Klasse Data speichert das Bild in einem QImage-Objekt und implementiert Funktionen zum Laden und Speichern sowie Skalieren und Drehen. Der Konstruktor erzeugt zunächst ein QImage im Format RGB32. In diesem Truecolor-Format sind für den roten, grünen und blauen Farbkanal je 8 Bit reserviert. Mit dem Aufruf von fill(0x808080) füllt man das Bild mit einem grauen Hintergrund.

Zum Laden und Speichern bietet QImage die Funktionen load(FileName) und save(FileName), wobei das Bildformat durch die Dateiendung bestimmt wird. Da QImage-Objekte von Qt per "Implicit Data Sharing" mit "Copy on Write" verwaltet werden, lassen sie sich in den Funktionen Data::scaleImage und Data::rotateImage einfach als Wert zuweisen.