Helmut Herold: Das Qt-Buch - Technische Hochschule Nürnberg

Transcrição

Helmut Herold: Das Qt-Buch - Technische Hochschule Nürnberg
Helmut Herold: Das Qt-Buch
Helmut Herold
Das Qt-Buch
Portable GUI-Programmierung unter
Linux / Unix / Windows
Alle in diesem Buch enthaltenen Programme, Darstellungen und Informationen wurden
nach bestem Wissen erstellt und mit Sorgfalt getestet. Dennoch sind Fehler nicht ganz auszuschließen. Aus diesem Grund ist das in dem vorliegenden Buch enthaltene ProgrammMaterial mit keiner Verpflichtung oder Garantie irgendeiner Art verbunden. Autoren
und die SuSE GmbH übernehmen infolgedessen keine Verantwortung und werden keine
daraus folgende Haftung übernehmen, die auf irgendeine Art aus der Benutzung dieses
Programm-Materials, oder Teilen davon, oder durch Rechtsverletzungen Dritter entsteht.
Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. in diesem Buch berechtigt auch ohne besondere Kennzeichnung nicht zu der Annahme, dass
solche Namen im Sinne der Warenzeichen- und Markenschutz-Gesetzgebung als frei zu
betrachten wären und daher von jedermann verwendet werden dürften.
Alle Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt und
sind möglicherweise eingetragene Warenzeichen. Die SuSE GmbH richtet sich im Wesentlichen nach den Schreibweisen der Hersteller. Andere hier genannte Produkte können
Warenzeichen des jeweiligen Herstellers sein.
Dieses Werk ist urheberrechtlich geschützt.
Alle Rechte, auch die der Übersetzung, des Nachdruckes und der Vervielfältigung des
Buches, oder Teilen daraus, vorbehalten. Kein Teil des Werkes darf ohne schriftliche Genehmigung des Verlages in irgendeiner Form (Druck, Fotokopie, Microfilm oder einem
anderen Verfahren), auch nicht für Zwecke der Unterrichtsgestaltung, reproduziert oder
unter Verwendung elektronischer Systeme verarbeitet, vervielfältigt oder verbreitet werden.
Die Deutsche Bibliothek – CIP-Einheitsaufnahme
Herold, Helmut:
Das Qt-Buch : portable GUI-Programmierung unter Linux/Unix/Windows /
Helmut Herold. – Nürnberg : SuSE-Press, 2001
ISBN 3-934678-76-9
© 2001 SuSE GmbH, Nürnberg (http://www.suse.de)
Umschlaggestaltung: Fritz Design GmbH, Erlangen
Gesamtlektorat: Nicolaus Millin / Dr. Markus Wirtz
Fachlektorat: Michael Eicks, Stefan Fent, Thomas Fricke, Bruno Gerz, Ralf Haferkamp,
Michael Hager, Harri Porten, Chris Schläger, Lukas Tinkl
Satz: LATEX
Druck: Kösel, Kempten
Printed in Germany on acid free paper.
Geleitwort
Wenn wir bei Trolltech an Qt denken, so denken wir an ein Werkzeug für „real
programmers“. Dies bedeutet keinesfalls, dass wir noch mit Fortran arbeiten oder
unser API nicht dokumentieren. „Real programmers“ sind für uns Profis, die ihre
Arbeit gemacht bekommen müssen – schnell, effizient und mit wartbarem Code in
bestmöglicher Qualität.
„Real programmers“ springen nicht auf den letzen Hype auf – wie auch immer die
Programmiersprache des Monats oder das Dogma der Woche lauten sollten. Für
sie zählt Ausführungsgeschwindigkeit, Eleganz, Wartbarkeit, Flexibilität und nicht
zuletzt die eigene Effizienz bei der Entwicklung der Programme. Für immer mehr
Projekte bedeutet das fast schon automatisch Qt und C ++.
Verglichen mit alternativen Toolkits benötigt eine mit Qt geschriebene Anwendung
in der Regel nur einen Bruchteil des Codes, ohne dabei langsamer zu sein. Wohlgemerkt, das gilt bereits für eine einzige Plattform, für cross-platform Anwendungen
fällt das Ergebnis für Qt noch viel günstiger aus. Unser Geheimrezept hierfür sind
– neben der konsequenten Anwendung Objekt-orientierter Techniken – sorgfältig
gestaltete APIs und Abstraktionen. Ziel ist es, die „normale“ Anwendung einer
Klasse so einfach wie nur irgend möglich zu machen, ohne dabei die avanciertere
Verwendung zu erschweren. Das setzt voraus, dass sich ein Toolkit nicht als Blackbox präsentiert, sondern als offene Lösung auch die dahinterliegenden Konzepte
offenbart.
Ein angenehmer Nebeneffekt soll hier nicht verschwiegen werden: Programmieren
mit Qt macht einfach Spaß! Zumindest mir ging das vor fünf Jahren so, als ich das
Toolkit erstmals als Anwender entdeckte – und bis heute hat sich daran nichts geändert. Und solange ich unsere Entwicklungsabteilung in ihrer Freizeit an privaten
Qt-basierten Projekten basteln sehe, wird sich daran auch nichts ändern.
Viel Spaß also auch Ihnen mit Qt und dem bis dato umfangreichsten gedruckten
Werk zur Qt-Programmierung!
Eine Bitte noch: Wenn sie einen Fehler in Qt gefunden oder einen Verbesserungsvorschlag zu machen haben, bitte zögern Sie nicht, uns eine Mail auf:
[email protected]
zu schicken.
Oslo, im Juni 2001
Matthias Ettrich
Danksagung
Zunächst möchte ich einmal Nico Millin und Dr. Markus Wirtz von SuSE PRESS
meinen Dank dafür aussprechen, dass sie beim Setzen dieses Buches mit über 1 000
Seiten nie den Mut verloren und immer nur positiv nach vorne – oder sagen wir in
diesem Falle besser: nach hinten – geblickt haben. Trotz aller Widrigkeiten, die das
Setzen eines Buches nun einmal mit sich bringt, war die Zusammenarbeit mit ihnen
immer angenehm. Dafür möchte ich mich an dieser Stelle nochmals recht herzlich
bedanken.
Des weiteren möchte ich mich noch bei meinen Kollegen von SuSE Labs bedanken,
die selbst in den größten Stresszeiten stets Zeit fanden, mir bei nervenden Fragen
zu helfen, und mir mit Rat und Tat zur Seite standen. Ein dickes Dankeschön an
Klaas Freitag, Michael Hager, Stefan Hundhammer, Chris Schläger und Adrian Schroeter.
Auch möchte ich mich bei Michael Eicks, Stefan Fent, Thomas Fricke, Bruno Gerz, Ralf
Haferkamp und Lukas Tinkl für ihre konstruktiven Beiträge und Anregungen während des Korrekturlesens herzlich bedanken, die ich sehr gerne in dieses Buch eingearbeitet habe.
Schließlich möchte ich mich noch bei der norwegischen Firma Trolltech bedanken,
ohne die es keine Qt-Bibliothek und somit auch nicht dieses Buch gäbe. Ein dickes
Dankeschön an Matthias Ettrich und Harri Porten von Trolltech für ihre Unterstützung, auf die ich gerade in der Endphase der Entstehung dieses Buches angewiesen
war.
Und natürlich danke ich meiner Frau Micha, die meiner Sucht zum Schreiben dieses Buches mit mehr Verständnis und Entbehrung entgegenkam als ich verdient
habe. Meinen beiden Kindern Niklas und Sascha möchte ich an dieser Stelle noch
versprechen, dass wir jetzt wieder öfter Angeln gehen.
Weisendorf-Neuenbürg, im Juni 2001
Dr. Helmut Herold
Die Themen im Überblick
Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1 Einführung in die Objektorientierung und C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2 Allgemeines zu Qt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
3 Grundlegende Konzepte und Konstrukte von Qt . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
4 Die wesentlichen Qt-Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
5 Zuordnung und Layout von Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
6 Vordefinierte Dialogfenster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
7 Portable Datei- und Directory-Operationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485
8 Vordefinierte Datentypen und Datenstrukturen (Containerklassen) . . . . . . . . . 521
9 Datenaustausch zwischen verschiedenen Applikationen . . . . . . . . . . . . . . . . . . . 593
10 Datum, Zeit und Zeitschaltuhren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617
11 Graphik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639
12 Bildformate und Cursorformen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 747
13 Animationen und Sounds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 775
14 Konsistente Eingaben und reguläre Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . 789
15 Tastaturfokus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 813
16 Ereignisbehandlung (Event-Handling) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 823
17 Signale und Slots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 869
IX
Die Themen im Überblick
18 Erstellen eigener Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 881
19 Thread-Programmierung und -Synchronisation . . . . . . . . . . . . . . . . . . . . . . . . . . . 917
20 Mehrsprachige Applikationen und Internationalisierung . . . . . . . . . . . . . . . . . . 943
21 Test- und Debugging-Möglichkeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 955
22 Netzwerkprogrammierung mit Qt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 965
23 Blockierungsfreie Datenübertragung im Hintergrund . . . . . . . . . . . . . . . . . . . . 1021
24 Parsen von XML-Dokumenten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1027
25 Qt-Programmierung mit anderen Bibliotheken und Sprachen . . . . . . . . . . . . 1079
26 Der Qt GUI-Designer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1117
27 Erstellen von Qt-Programmen mit KDevelop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1143
28 Das Tool tmake . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1149
X
Inhaltsverzeichnis
Einleitung
1
1 Einführung in die Objektorientierung und C++
1.1 Objektorientierung in der realen Welt
.
.
.
.
.
1.2 Objektorientierung in der Software
.
.
.
.
.
1.3 Nicht-objektorientierte Erweiterungen in C++
.
.
.
1.3.1 Zeilen-Kommentare mit // .
.
.
.
.
.
1.3.2 Variablen-Deklarationen (auch im Anweisungsteil) .
1.3.3 Default-Argumente bei Funktionsaufrufen
.
.
1.3.4 Überladen von Funktionen .
.
.
.
.
.
1.3.5 Inline-Funktionen
.
.
.
.
.
.
.
1.3.6 Referenzen/Referenz-Operator .
.
.
.
.
1.3.7 Neue Ein- und Ausgabebibliothek
.
.
.
.
1.3.8 Operatoren new und delete
.
.
.
.
.
1.3.9 Neuer Datentyp bool .
.
.
.
.
.
.
1.3.10 Weglassen der Schlüsselwörter struct, union und enum
bei Deklarationen .
.
.
.
.
.
.
.
1.3.11 Funktionen in Strukturen – Erster wesentlicher Schritt zur
Objektorientierung
.
.
.
.
.
.
.
1.3.12 Beispiel: Mastermind gegen Computer
.
.
.
1.4 Objektorientierte Erweiterungen in C++
.
.
.
.
1.4.1 Wichtige Begriffe aus der Welt der Objektorientierung
1.4.2 Klassen .
.
.
.
.
.
.
.
.
.
1.4.3 Überladen von Operatoren .
.
.
.
.
.
1.4.4 Vererbung
.
.
.
.
.
.
.
.
.
1.4.5 Templates
.
.
.
.
.
.
.
.
.
37
51
54
54
55
65
72
105
2 Allgemeines zu Qt
2.1 Was ist Qt und warum Qt?
.
.
.
.
2.2 Der Begriff „Widget“
.
.
.
.
.
2.3 Die Qt-Online-Dokumentation im HTML-Format
2.4 Die Qt-Dokumentation als Postscript-Datei
.
2.5 Kompilieren von Qt-Programmen .
.
.
115
115
117
117
119
119
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
11
14
16
16
16
17
18
19
20
25
35
36
37
XI
Inhaltsverzeichnis
3 Grundlegende Konzepte und Konstrukte von Qt
3.1 Erstes Qt-Programm mit Text und Buttons
.
.
.
.
3.2 Mehr zum Signal-Slot-Konzept von Qt .
.
.
.
.
3.2.1 Schiebebalken und Buttons zum Erhöhen/Erniedrigen von
LCD-Nummern
.
.
.
.
.
.
.
.
3.2.2 Schiebebalken und Buttons zum Ändern der Schriftgröße mit
Textanzeige
.
.
.
.
.
.
.
.
.
3.2.3 Regeln für die Deklaration eigener Slots und Signale
3.3 Die Klasse QString für das Arbeiten mit Zeichenketten unter Qt
3.4 Farbmodelle, Farbgruppen und Paletten im Qt
.
.
.
3.4.1 Farbmodelle (QColor) .
.
.
.
.
.
.
3.4.2 Farbgruppen (QColorGroup)
.
.
.
.
.
3.4.3 Palette eines Widget (QPalette)
.
.
.
.
3.4.4 Beispiele
.
.
.
.
.
.
.
.
.
3.5 Malprogramm mit Menüs, Events und mehr .
.
.
.
3.5.1 Eine erste einfache Version eines Malprogramms
.
3.5.2 Eine zweite, etwas erweiterte Version des Malprogramms
3.5.3 Eine dritte Version des Malprogramms mit Menüs
.
3.5.4 Eine vierte Version des Malprogramms mit Laufbalken
3.5.5 Eine fünfte Version des Malprogramms mit einigen netten
Erweiterungen
.
.
.
.
.
.
.
.
3.5.6 Eine letzte Version des Malprogramms mit Speichern und
Laden von Dateien
.
.
.
.
.
.
.
4 Die wesentlichen Qt-Widgets
4.1 Allgemeine Widget-Methoden und -Parameter
.
.
.
4.1.1 Allgemeine Widget-Methoden
.
.
.
.
.
4.1.2 Parameter-Konventionen für die meisten Konstruktoren
4.2 Der Widget-Stil .
.
.
.
.
.
.
.
.
.
4.3 Buttons
.
.
.
.
.
.
.
.
.
.
.
4.3.1 Pushbuttons (QPushButton)
.
.
.
.
.
4.3.2 Radiobuttons (QRadioButton) und Checkboxen (QCheckBox)
.
.
.
.
.
.
.
.
.
.
4.3.3 Pushbuttons mit der Wirkungsweise von Radiobuttons
4.3.4 Gruppieren von Buttons (QButtonGroup)
.
.
4.3.5 Beispiel zu Buttons
.
.
.
.
.
.
.
4.3.6 Beispiel zu Gruppen von Buttons
.
.
.
.
4.3.7 Beispiel zu Popupmenüs bei Pushbuttons .
.
.
4.3.8 Übung: Synchronisieren von Radio- mit Togglebuttons
4.4 Auswahl-Widgets (List- und Komboboxen)
.
.
.
.
4.4.1 Listboxen (QListBox) .
.
.
.
.
.
.
4.4.2 Komboboxen (QComboBox) .
.
.
.
.
.
4.4.3 Beispiel zu List- und Komboboxen
.
.
.
.
4.4.4 Übung: Eingabe von Daten über List- und Komboboxen
4.5 Schiebebalken-, Drehknopf- und Spinbox-Widgets
.
.
4.5.1 Schiebebalken (QSlider)
.
.
.
.
.
.
XII
123
124
128
128
131
135
137
146
146
149
150
152
160
160
165
166
171
178
189
199
201
201
202
203
204
204
205
205
206
207
210
213
216
216
216
218
219
223
223
224
Inhaltsverzeichnis
4.5.2
4.5.3
4.5.4
4.5.5
4.5.6
4.6
4.7
4.8
4.9
Drehknopfeinstellungen (QDial)
.
.
.
.
Spinboxen (QSpinBox)
.
.
.
.
.
.
Beispiel zu Schiebebalken und Spinboxen .
.
.
Beispiel zur Klasse QDial
.
.
.
.
.
.
Übung: Größeneinstellung eines Rechtecks über Schiebebalken und Spinboxen
.
.
.
.
.
.
.
Widgets zum Anzeigen von Informationen
.
.
.
.
4.6.1 Einfache Labels (QLabel)
.
.
.
.
.
.
4.6.2 Komfortable Textanzeige (QTextView, QTextBrowser)
4.6.3 7-Segment-LCD-Anzeige (QLCDNumber)
.
.
.
4.6.4 Beispiel zu Labels: Anzeige von Graphikbildern
.
4.6.5 Beispiel zur Anzeige von RichText
.
.
.
.
4.6.6 Beispiel zu LCD-Zahlen: Synchronisierte Darstellung in verschiedenen Zahlensystemen
.
.
.
.
.
4.6.7 Übung: Mausposition als LCD-Nummer und als Fadenkreuz
Texteingabefelder
.
.
.
.
.
.
.
.
.
4.7.1 Einzeilige Texteingabefelder (QLineEdit)
.
.
4.7.2 Mehrzeilige Texteingabefelder (QMultiLineEdit) .
4.7.3 Beispiel zu Texteingabefeldern: Potenzieren von Zahlen
4.7.4 Weiteres Beispiel zu einzeiligen Texteingabefeldern .
4.7.5 Übung: Synchronisierte Darstellung in verschiedenen Zahlensystemen .
.
.
.
.
.
.
.
.
Menüs
.
.
.
.
.
.
.
.
.
.
.
4.8.1 Die Basisklasse für Menüs (QMenuData)
.
.
.
4.8.2 Beispiel: Auswahl einer Farbe über ein Menü
.
.
4.8.3 Festlegen von Beschleunigern (Accelerators)
.
.
4.8.4 Popupmenüs, deren Inhalt sich dynamisch ändert
.
4.8.5 Die Menüleiste (QMenuBar)
.
.
.
.
.
4.8.6 Kontextmenüs
.
.
.
.
.
.
.
.
4.8.7 Beispiel zu Menüs
.
.
.
.
.
.
.
4.8.8 Übung: Einstellen des Font über Menüs, Beschleuniger oder
Kontextmenüs
.
.
.
.
.
.
.
.
Hauptfenster mit Menüs, Werkzeugleisten, Statuszeile und Hilfstexten
.
.
.
.
.
.
.
.
.
.
.
.
4.9.1 Das Hauptfenster (QMainWindow)
.
.
.
.
4.9.2 Werkzeugleisten (QToolBar und QToolButton)
.
4.9.3 Einfaches Beispiel zu QMainWindow mit Menüs und Werkzeugleisten
.
.
.
.
.
.
.
.
.
4.9.4 Kurze und längere Hilfstexte (QToolTip, QToolTipGroup
und QWhatsThis)
.
.
.
.
.
.
.
4.9.5 Beispiel: Dynamische Tooltips (Möglichkeit 1) .
.
4.9.6 Beispiel: Dynamische Tooltips (Möglichkeit 2) .
.
4.9.7 Statuszeilen (QStatusBar) .
.
.
.
.
.
4.9.8 Beispiel zu QMainWindow mit Werkzeugleisten, Statuszeile
und Hilfstexten
.
.
.
.
.
.
.
.
4.9.9 Übung: Einfacher Texteditor
.
.
.
.
.
225
227
228
231
235
235
235
236
237
238
239
243
246
246
246
247
249
251
254
254
255
256
258
259
259
259
260
264
264
265
267
268
271
272
275
279
280
289
XIII
Inhaltsverzeichnis
4.10 Füllbalken .
.
.
.
.
.
.
.
.
.
.
4.10.1 Horizontaler Füllbalken (QProgressBar)
.
.
4.10.2 Dialog mit Text, Füllbalken und Cancel-Button (QProgressDialog)
.
.
.
.
.
.
.
.
.
4.10.3 Beispiel: Demoprogramm zu QProgressDialog
.
4.10.4 Übung: Steuern eines Füllbalkens über Schiebebalken
4.10.5 Übung: Würfeln der Gaußschen Glockenkurve .
.
4.11 Listenansichten
.
.
.
.
.
.
.
.
.
4.11.1 Die Klasse QListView
.
.
.
.
.
.
4.11.2 Die Klasse QListViewItem
.
.
.
.
.
4.11.3 Die Klasse QListViewItemIterator
.
.
.
4.11.4 Einfaches Beispiel zu einer Listenansicht
.
.
.
4.11.5 Beispiel: Directorybrowser in Form einer Listenansicht
4.11.6 Übung: Qt-Klassenhierarchie in einer Listenansicht .
4.12 Fenster mit Laufbalken (Scrollviews)
.
.
.
.
.
4.12.1 Die Klasse QScrollView
.
.
.
.
.
.
4.12.2 Vorgehensweisen abhängig von Fensterfläche
.
.
4.12.3 Beispiel zu den unterschiedlichen Vorgehensweisen .
4.12.4 Die Klasse QScrollBar
.
.
.
.
.
.
4.12.5 Beispiel: Scrollen eines Bildes mit QScrollBar
.
4.12.6 Übung: Geschachtelte Fenster mit Laufbalken .
.
4.13 Tabellen
.
.
.
.
.
.
.
.
.
.
.
4.13.1 Die Klasse QTableView für einfache Tabellen .
.
4.13.2 Beispiel zu QTableview: Multiplikationsaufgaben .
4.13.3 Die Klasse QTable für Tabellen im Spreadsheet-Stil .
4.13.4 Die Klasse QHeader
.
.
.
.
.
.
.
4.13.5 Die Klassen QTableItem und QTableSelection .
4.13.6 Beispiel: Spreadsheet für eine Personalverwaltung
.
4.13.7 Übung: Tabelle mit Multiplikationsaufgaben
.
.
5 Zuordnung und Layout von Widgets
5.1 Zuordnung von Widgets untereinander .
.
.
5.1.1 Die Klasse QFrame
.
.
.
.
.
5.1.2 Die Klasse QGroupBox
.
.
.
.
5.1.3 Die Klasse QButtonGroup .
.
.
.
5.1.4 Die Klasse QSplitter
.
.
.
.
5.1.5 Die Klasse QWidgetStack .
.
.
.
5.2 Layout von Widgets .
.
.
.
.
.
.
5.2.1 Einfaches Layout mit QHBox, QVBox und QGrid
5.2.2 Fortgeschrittenes Layout mit QLayout
.
5.2.3 Benutzerdefinierte Layouts .
.
.
.
6 Vordefinierte Dialogfenster
6.1 Die Basisklasse QDialog .
.
.
.
.
6.2 Klasse QColorDialog zur Auswahl einer Farbe
6.3 Klasse QFileDialog zur Auswahl einer Datei
XIV
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
290
290
294
296
300
300
302
302
304
305
306
308
312
312
312
316
317
326
327
333
333
333
336
341
344
345
345
350
.
.
.
.
.
.
.
.
.
.
351
352
352
358
363
363
370
373
374
377
397
.
.
.
417
418
421
423
Inhaltsverzeichnis
6.4
6.5
6.6
Klasse QFontDialog zur Auswahl eines Font
.
.
.
Klasse QMessageBox für Mitteilungen .
.
.
.
.
Klasse QTabDialog zur Stapelung von Widgets im Karteikartenformat
.
.
.
.
.
.
.
.
.
.
.
6.7 Klasse QWizard zum Blättern in einer vorgegebenen Menge von
Widgets
.
.
.
.
.
.
.
.
.
.
.
6.8 Klasse QPrinter zum Drucken mit möglichen Druckereinstellungen
.
.
.
.
.
.
.
.
.
.
.
.
6.9 Klasse QInputDialog für einfache Benutzereingaben
.
6.10 Klasse QProgressDialog zur Fortschrittsanzeige in einem Prozentbalken
.
.
.
.
.
.
.
.
.
.
7 Portable Datei- und Directory-Operationen
7.1 Die Basisklasse QIODevice für Zugriffe auf E/A-Geräte
.
7.2 Klasse QFile für Datei-Operationen
.
.
.
.
.
7.3 Klasse QBuffer für Speicherzugriffe wie bei einem E/A-Gerät
7.4 Die Klassen QTextStream und QDataStream
.
.
.
7.4.1 Klasse QTextStream zum Lesen und Schreiben von Text in
Dateien .
.
.
.
.
.
.
.
.
.
7.4.2 Klasse QDataStream zum plattformunabhängigen Lesen und
Schreiben in Dateien
.
.
.
.
.
.
.
7.5 Klasse QFileInfo zum Erfragen von Informationen zu Dateien
7.6 Klasse QDir für Directory-Operationen .
.
.
.
.
8 Vordefinierte Datentypen und Datenstrukturen (Containerklassen)
8.1 Vordefinierte Datentypen (QPoint, QSize und QRect)
.
8.1.1 Die Klasse QPoint
.
.
.
.
.
.
.
8.1.2 Die Klasse QSize .
.
.
.
.
.
.
.
8.1.3 Die Klasse QRect .
.
.
.
.
.
.
.
8.1.4 Übung: Durchschnitt und umschließendes Rechteck von zwei
Rechtecken
.
.
.
.
.
.
.
.
.
8.2 Data-Sharing
.
.
.
.
.
.
.
.
.
.
8.3 Arrays
.
.
.
.
.
.
.
.
.
.
.
8.3.1 Die Klasse QArray
.
.
.
.
.
.
.
8.3.2 Die Klasse QVector
.
.
.
.
.
.
.
8.3.3 Die Klasse QByteArray
.
.
.
.
.
.
8.3.4 Die Klasse QBitArray
.
.
.
.
.
.
8.3.5 Die Klasse QPointArray
.
.
.
.
.
.
8.4 Hashtabellen und zugehörige Iterator-Klassen
.
.
.
8.4.1 Die Klasse QDict .
.
.
.
.
.
.
.
8.4.2 QDictIterator - Eine Iterator-Klasse für QDict
.
8.4.3 Die Klassen QAsciiDict, QPtrDict, QAsciiDictIterator und QPtrDictIterator
.
.
.
.
.
8.4.4 Die Klassen QIntDict und QIntDictIterator
.
8.4.5 Die Klasse QCache
.
.
.
.
.
.
.
8.4.6 QCacheIterator – Eine Iterator-Klasse für QCache
431
436
446
456
463
477
483
485
485
487
491
493
493
497
506
513
521
523
523
525
527
530
530
535
535
540
540
540
543
547
548
552
557
557
559
561
XV
Inhaltsverzeichnis
8.4.7 Die Klassen QAsciiCache und QAsciiCacheIterator
8.4.8 Die Klassen QIntCache und QIntCacheIterator
8.4.9 Die Klasse QMap für wertebasierende Hashtabellen .
8.4.10 Übung: Cross-Reference-Liste für C-Programme
.
Listen und zugehörige Iterator-Klassen .
.
.
.
.
8.5.1 Die Klasse QList .
.
.
.
.
.
.
.
8.5.2 QListIterator – Eine Iterator-Klasse für QList
.
8.5.3 Klasse QValueList – Eine wertebasierende Liste
.
8.5.4 Die Iterator-Klassen QValueListIterator und QValueListConstIterator
.
.
.
.
.
.
8.5.5 Die Klasse QStringList
.
.
.
.
.
.
8.5.6 Die Klassen QStrList und QStrIList
.
.
.
8.5.7 Übung: Das Josephus-Spiel .
.
.
.
.
.
Stacks (LIFO-Strategie)
.
.
.
.
.
.
.
.
8.6.1 Die referenzbasierende Klasse QStack
.
.
.
8.6.2 Die wertebasierende Klasse QValueStack
.
.
8.6.3 Übung: Umwandlung einer Dezimalzahl in Dualzahl
Queues (FIFO-Strategie) .
.
.
.
.
.
.
.
8.7.1 Die Klasse QQueue
.
.
.
.
.
.
.
8.7.2 Beispiel: Simulation einer Warteschlange
.
.
.
8.7.3 Übung: Realisierung einer Warteschlange .
.
.
562
562
563
566
567
567
571
573
9 Datenaustausch zwischen verschiedenen Applikationen
9.1 Verwendung des Clipboard
.
.
.
.
.
.
.
9.1.1 Die Klasse QClipBoard
.
.
.
.
.
.
9.1.2 Beispiel: Austausch von Texten über das Clipboard .
9.1.3 Beispiel: Austausch von Bildern über das Clipboard
9.1.4 Übung: Zufälliges Austauschen von Bildern über das Clipboard
.
.
.
.
.
.
.
.
.
.
9.2 Drag-and-Drop .
.
.
.
.
.
.
.
.
.
9.2.1 Drag-and-Drop von Text oder Bildern in Qt
.
.
9.2.2 Drag-and-Drop in Verbindung mit dem Clipboard
.
9.2.3 Definieren von eigenen Typen für Drag-and-Drop
.
9.2.4 Die Klasse QUriDrag zum Austausch von Dateinamen
9.2.5 Übung: Zusammenstellen eines Kartenblattes mit Drag-andDrop
.
.
.
.
.
.
.
.
.
.
593
593
594
594
596
8.5
8.6
8.7
10 Datum, Zeit und Zeitschaltuhren
10.1 Die Klasse QDate
.
.
.
.
.
.
.
.
.
10.1.1 Beispiel: Demonstrationsprogramm zur Klasse QDate
10.1.2 Beispiel: Tagesdifferenz zwischen zwei Daten
.
.
10.1.3 Übung: Ermitteln des Ostertermins für ein Jahr
.
10.2 Die Klasse QTime
.
.
.
.
.
.
.
.
.
10.2.1 Beispiel: Addition von zwei Zeiten
.
.
.
.
10.2.2 Beispiel: Ein Reaktionstest .
.
.
.
.
.
10.2.3 Übung: Anzeige der aktuellen Zeit mit Fortschrittsbalken
XVI
575
577
580
582
582
582
584
586
587
587
588
591
598
598
598
607
609
615
615
617
617
619
621
622
623
624
625
628
Inhaltsverzeichnis
10.3 Die Klasse QDateTime
.
.
.
.
.
.
.
.
10.3.1 Beispiel: Ausgeben der Sekunden und Tage bis zu fixen Daten .
.
.
.
.
.
.
.
.
.
.
10.3.2 Übung: Automatische Arbeitszeiterfassung
.
.
10.4 Zeitschaltuhren (Timer)
.
.
.
.
.
.
.
.
10.4.1 Die Klasse QTimer
.
.
.
.
.
.
.
10.4.2 Timer-Events
.
.
.
.
.
.
.
.
10.4.3 Übung: Realisierung einer Ampelsteuerung
.
.
628
630
630
632
632
634
637
11 Graphik
11.1 Allozieren von Farben
.
.
.
.
.
.
.
.
11.1.1 Farballozierung mit Methoden der Klasse QColor
.
11.1.2 Farballozierung mit Methoden der Klasse QApplication
11.2 Grundlegendes zur Klasse QPainter
.
.
.
.
.
11.2.1 Konstruktoren und Methoden der Klasse QPainter
11.2.2 Beispiele
.
.
.
.
.
.
.
.
.
11.3 Einstellungen für QPainter-Objekte
.
.
.
.
.
11.3.1 Einstellen des Zeichenstifts .
.
.
.
.
.
11.3.2 Festlegen eines Füllmusters .
.
.
.
.
.
11.3.3 Festlegen eines neuen Zeichenfonts
.
.
.
.
11.3.4 Beispiel: Zufällige Zeichenstifte mit allen Füllmustern
11.3.5 Übung: Interaktives Einstellen von Stift und Füllmuster
11.4 Positionieren und Ausgeben von Figuren und Text
.
.
11.4.1 Positionieren .
.
.
.
.
.
.
.
.
11.4.2 Zeichnen geometrischer Figuren .
.
.
.
.
11.4.3 Ausgeben von Text
.
.
.
.
.
.
.
11.5 Alternatives Ausgeben von Figuren
.
.
.
.
.
11.5.1 Funktionen aus <qdrawutil.h>
.
.
.
.
11.5.2 Beispielprogramm zu den Funktionen aus <qdrawutil.h>
11.5.3 Übung: Game of Life
.
.
.
.
.
.
.
11.6 Transformationen
.
.
.
.
.
.
.
.
.
11.6.1 Einfache World-Transformationen
.
.
.
.
11.6.2 World-Transformationen mit der Klasse QWMatrix .
11.6.3 View-Transformationen
.
.
.
.
.
.
11.7 Clipping
.
.
.
.
.
.
.
.
.
.
.
11.7.1 Festlegen von Clipping-Regionen
.
.
.
.
11.7.2 Die Klasse QRegion
.
.
.
.
.
.
.
11.7.3 Beispielprogramm zu Clipping
.
.
.
.
.
11.7.4 Übung: Vorbeifliegende Gegenstände an Fensterwand
11.8 QPainter-Zustand sichern und wiederherstellen
.
.
11.8.1 Die QPainter-Methoden save() und restore()
11.8.2 Beispiel: Drehen einer sich ständig ändernden Figur
11.8.3 Übung: QPainter-Zustände im Stack
.
.
.
11.9 Flimmerfreie Darstellung
.
.
.
.
.
.
.
11.9.1 Ausschalten der Hintergrundfarbe
.
.
.
.
11.9.2 Vermeiden überflüssigen Zeichnens
.
.
.
.
639
639
640
641
642
643
643
650
650
650
652
652
655
657
657
657
660
670
670
671
674
675
675
688
691
708
708
708
709
711
712
712
712
716
716
717
718
XVII
Inhaltsverzeichnis
11.9.3 Doppel-Pufferung
.
.
.
.
11.10Die QCanvas-Klassen
.
.
.
.
.
11.10.1 Die Klasse QCanvas
.
.
.
.
11.10.2 Die Klasse QCanvasItem
.
.
.
11.10.3 Die Klasse QCanvasLine
.
.
.
11.10.4 Die Klasse QCanvasRectangle
.
11.10.5 Die Klasse QCanvasEllipse
.
.
11.10.6 Die Klasse QCanvasPolygon
.
.
11.10.7 Die Klasse QCanvasPolygonalItem
11.10.8 Die Klasse QCanvasSprite
.
.
11.10.9 Die Klasse QCanvasText
.
.
.
11.10.10Die Klasse QCanvasPixmap
.
.
11.10.11Die Klasse QCanvasPixmapArray
.
11.10.12Die Klasse QCanvasView
.
.
.
11.10.13Demoprogramm zu den QCanvas-Klassen
11.10.14Übung zu den QCanvas-Klassen
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
719
727
727
729
731
731
732
732
733
733
734
734
735
735
736
745
12 Bildformate und Cursorformen
12.1 Pixmap-Klassen
.
.
.
.
.
.
.
.
.
12.1.1 Format einer Pixmap
.
.
.
.
.
.
.
12.1.2 Die Klasse QPixmap
.
.
.
.
.
.
.
12.1.3 Die Klasse QPixmapCache .
.
.
.
.
.
12.1.4 Die Klasse QBitmap
.
.
.
.
.
.
.
12.1.5 Beispiel: Erstellen eines Screenshot durch Ziehen der Maus
12.1.6 Übung: Screenshot vom Bildschirm oder eines Teilbereichs
12.2 Die Klasse QCursor
.
.
.
.
.
.
.
.
12.2.1 Konstruktoren und Methoden der Klasse QCursor .
12.2.2 Beispiel zu vor- und benutzerdefinierten Cursorformen
12.2.3 Übung: Ändern des Mauscursor bei einem Mausklick
12.3 Die Klassen QImage und QImageIO
.
.
.
.
.
12.3.1 Konstruktoren und Methoden der Klasse QImage
.
12.3.2 Routinen zum Setzen bzw. Erfragen einzelner Pixel .
12.3.3 Die Klasse QImageIO für benutzerdefinierte Bildformate
12.3.4 Beispiel: Einfache Bildbearbeitung
.
.
.
.
12.3.5 Übung: Erweiterte Bildbearbeitung
.
.
.
.
12.4 Die Klasse QPicture
.
.
.
.
.
.
.
.
12.4.1 Konstruktoren und Methoden der Klasse QPicture
12.4.2 Beispiel: Demoprogramm zur Klasse QPicture
.
747
747
747
748
751
751
752
754
754
755
757
759
759
760
763
764
765
770
770
771
771
13 Animationen und Sounds
13.1 Animationen mit der Klasse QMovie
.
.
.
.
.
13.1.1 Konstruktoren und Methoden der Klasse QMovie
.
13.1.2 Beispiel: Abspielen von Filmen
.
.
.
.
.
13.1.3 Beispiel: Einstellen der Abspielgeschwindigkeit
.
13.1.4 Übung: Anzeigen einzelner Frames (Bilder) eines Films
13.2 Sound mit der Klasse QSound .
.
.
.
.
.
.
775
775
775
778
783
785
786
XVIII
Inhaltsverzeichnis
13.2.1 Konstruktor und Methoden der Klasse QSound
.
13.2.2 Beispiel: Demoprogramm zur Klasse QSound
.
.
13.2.3 Übung: Auswahl einer Sound-Datei über QFileDialog
14 Konsistente Eingaben und reguläre Ausdrücke
14.1 Konsistente Eingaben mit Klasse QValidator
.
.
14.1.1 Die Basisklasse QValidator
.
.
.
.
14.1.2 Die Klasse QIntValidator
.
.
.
.
14.1.3 Die Klasse QDoubleValidator
.
.
.
14.2 Reguläre Ausdrücke (Klasse QRegExp) .
.
.
.
14.2.1 Unterschiedliche Arten von regulären Ausdrücken
14.2.2 Escape-Sequenzen
.
.
.
.
.
.
14.2.3 Konstruktoren und Methoden der Klasse QRegExp
786
786
788
.
.
.
.
.
.
.
.
789
790
790
794
796
799
800
801
802
15 Tastaturfokus
15.1 Einstellen und Erfragen von Fokusregeln
.
.
.
.
15.2 Reihenfolge beim Wechseln des Tastaturfokus mit der Tabtaste
813
813
817
16 Ereignisbehandlung (Event-Handling)
16.1 Allgemeines zu Events
.
.
.
.
.
.
.
.
16.2 Die Basisklasse QEvent und die davon abgeleiteten Event-Klassen
16.2.1 Die Basisklasse QEvent
.
.
.
.
.
.
16.2.2 Mal-Events (QPaintEvent)
.
.
.
.
.
16.2.3 Maus-Events (QMouseEvent und QWheelEvent)
.
16.2.4 Tastatur-Events (QKeyEvent)
.
.
.
.
.
16.2.5 Timer-Events (QTimerEvent)
.
.
.
.
.
16.2.6 Fokus-Events (QFocusEvent)
.
.
.
.
.
16.2.7 Größenänderungs-Events (QResizeEvent)
.
.
16.2.8 Positionsänderungs-Events (QMoveEvent)
.
.
16.2.9 Eintritts- und Austritts-Events
.
.
.
.
.
16.2.10 Versteck-, Sichtbarkeits- und Schließ-Events (QHideEvent,
QShowEvent, QCloseEvent)
.
.
.
.
.
16.2.11 Subwidget-Events (QChildEvent)
.
.
.
.
16.2.12 Drag-and-Drop-Events (QDragEnterEvent, QDragMoveEvent, QDragLeaveEvent, QDropEvent)
.
.
16.3 Event-Filter
.
.
.
.
.
.
.
.
.
.
16.4 Senden eigener Events
.
.
.
.
.
.
.
.
16.5 Benutzerdefinierte Events (QCustomEvent) .
.
.
.
823
823
824
824
826
827
834
840
841
843
845
846
17 Signale und Slots
17.1 Verbindung zwischen einem Signal und einer Slotroutine
.
17.2 Verbindung zwischen einem Signal und einem anderen Signal
17.3 Auflösen bzw. temporäres Ausschalten von bestehenden Signal-SlotVerbindungen
.
.
.
.
.
.
.
.
.
.
17.4 Verbinden mehrerer Buttons mit einer Slotroutine
.
.
17.5 Senden eigener Signale mit QSignal
.
.
.
.
.
869
869
871
848
852
854
855
858
862
871
873
877
XIX
Inhaltsverzeichnis
18 Erstellen eigener Widgets
18.1 Grundlegende Vorgehensweise beim Entwurf eigener Widgets
18.2 Beispiel: Implementieren eines Funktionsplotters .
.
.
18.2.1 Beschreibung des Funktionsplotters
.
.
.
.
18.2.2 Headerdatei für den Funktionsplotter
.
.
.
18.2.3 Implementierung des Funktionsplotters
.
.
.
18.2.4 Beispiel: Plotten einer Sinusfunktion .
.
.
.
18.2.5 Beispiel: Plotten einer Funktion, die der Benutzer interaktiv
eingibt
.
.
.
.
.
.
.
.
.
.
18.2.6 Übung: Plotten der Funktion 1-exp(0.5x) und deren Ableitung
.
.
.
.
.
.
.
.
.
.
18.3 Beispiel: Implementieren einer Bildertabelle .
.
.
.
18.3.1 Beschreibung des Bildertabellen-Widget
.
.
.
18.3.2 Headerdatei für das Bildertabellen-Widget
.
.
18.3.3 Implementierung das Bildertabellen-Widget
.
.
18.3.4 Beispiel: Ein Memory-Spiel .
.
.
.
.
.
18.3.5 Beispiel: Ein Puzzle-Spiel
.
.
.
.
.
.
18.3.6 Beispiel: Ein Poker-Spiel
.
.
.
.
.
.
18.3.7 Übung: Ein Bilderbrowser für Dias
.
.
.
.
898
898
898
900
901
903
906
909
915
19 Thread-Programmierung und -Synchronisation
19.1 Die Klasse QThread
.
.
.
.
.
.
19.2 Synchronisation von Threads mit QMutex
.
.
19.3 Synchronisation von Threads mit QSemaphore
.
19.4 Synchronisation von Threads mit QWaitCondition
19.5 Übung: Zuteilung von Plätzen in einem Speiseraum
.
.
.
.
.
.
.
.
.
.
917
917
922
927
937
942
20 Mehrsprachige Applikationen und Internationalisierung
20.1 Die Klasse QString für Unicode
.
.
.
.
20.2 Automatische Übersetzung in andere Sprachen
.
20.3 Automatische Anpassung an lokale Besonderheiten
20.4 Konvertierung von Text-Kodierungen
.
.
.
20.5 Übung: Landabhängiges Einblenden eines Datums
.
.
.
.
.
.
.
.
.
.
943
943
944
953
954
954
21 Test- und Debugging-Möglichkeiten
21.1 Testausgaben mit qDebug(), qWarning() und qFatal()
21.2 Die Makros ASSERT() und CHECK_PTR()
.
.
.
.
21.3 Debuggen mittels Objektnamen
.
.
.
.
.
.
21.4 Übung: Testausgaben in eine Log-Datei .
.
.
.
.
955
955
957
959
961
22 Netzwerkprogrammierung mit Qt
22.1 Protokollunabhängige Netzwerkprogrammierung
22.1.1 Die Klasse QUrlOperator .
.
.
22.1.2 Die Klasse QUrl
.
.
.
.
.
22.1.3 Die Klasse QUrlInfo .
.
.
.
22.1.4 Die Klasse QNetworkOperation
.
965
965
965
974
976
978
XX
.
.
.
.
.
.
.
.
.
.
.
.
.
.
881
881
882
882
883
884
888
891
Inhaltsverzeichnis
22.1.5 Beispiel: Herunterladen einer Datei von einem FTP-Server
mit Fortschrittsanzeige
.
.
.
.
.
.
22.1.6 Übung: Gleichzeitiges Herunterladen mehrerer Dateien mit
Fortschrittsanzeigen
.
.
.
.
.
.
.
22.2 Implementieren eigener Netzwerkprotokolle mit QNetworkProtocol
.
.
.
.
.
.
.
.
.
.
.
.
22.2.1 Vorgehensweise beim Implementieren eines eigenen Netzwerkprotokolls
.
.
.
.
.
.
.
.
22.2.2 Die Klasse QNetworkProtocol
.
.
.
.
22.2.3 Die Klasse QFtp
.
.
.
.
.
.
.
.
22.2.4 Die Klasse QLocalFs .
.
.
.
.
.
.
22.3 Socket-Programmierung .
.
.
.
.
.
.
.
22.3.1 Die Klasse QSocket
.
.
.
.
.
.
.
22.3.2 Die Klasse QSocketDevice
.
.
.
.
.
22.3.3 Die Klasse QServerSocket
.
.
.
.
.
22.3.4 Beispiel: Ein einfacher http-Dämon
.
.
.
.
22.3.5 Beispiel: Einfache Implementierung des nntp-Protokolls
22.4 Low-level Socket-Programmierung
.
.
.
.
.
22.4.1 Die Klasse QSocketNotifier .
.
.
.
.
22.4.2 Die Klasse QHostAddress .
.
.
.
.
.
22.4.3 DNS-Lookups mit der Klasse QDns
.
.
.
.
981
984
984
984
990
992
993
993
993
996
996
997
1000
1005
1005
1008
1009
23 Blockierungsfreie Datenübertragung im Hintergrund
1021
23.1 Die Klasse QDataSource
.
.
.
.
.
.
.
1021
23.2 Die Klasse QDataSink
.
.
.
.
.
.
.
.
1022
23.3 Die Klasse QDataPump
.
.
.
.
.
.
.
.
1023
23.4 Beispiel: Demoprogramm zu den Klassen QDataSource, QDataSink und QDataPump
.
.
.
.
.
.
.
.
1023
23.5 Übung: Zählen der 0- und 1-Bits in Dateien
.
.
.
.
1025
24 Parsen von XML-Dokumenten
24.1 SAX2 und die zugehörigen Qt-Klassen .
.
.
.
.
24.1.1 Die SAX2-Schnittstelle von Qt
.
.
.
.
.
24.1.2 Die Klassen der SAX2-Schnittstelle von Qt
.
.
24.1.3 Beispiel: Plotten einer Funktion über ein XML-Dokument
24.1.4 Beispiel: Anzeigen von XML-Dokumenten im Richtext-Format
.
.
.
.
.
.
.
.
.
.
24.2 DOM Level 1 und die zugehörigen Qt-Klassen
.
.
.
24.2.1 Die DOM-Schnittstelle von Qt
.
.
.
.
.
24.2.2 Die Klassen der DOM-Schnittstelle von Qt
.
.
24.2.3 Beispiel: Plotten einer Funktion über ein XML-Dokument
24.2.4 Beispiel:Anzeigen von XML-Dokumenten im Richtext-Format
.
.
.
.
.
.
.
.
.
.
24.3 Übung: Plotten einer Funktion als Linie oder in Balkenform über ein
XML-Dokument
.
.
.
.
.
.
.
.
.
1027
1027
1027
1032
1042
1048
1053
1053
1057
1072
1075
1077
XXI
Inhaltsverzeichnis
25 Qt-Programmierung mit anderen Bibliotheken und Sprachen
25.1 OpenGL-Programmierung mit Qt .
.
.
.
.
.
25.1.1 Die Klasse QGLWidget
.
.
.
.
.
.
25.1.2 Die Klasse QGLContext
.
.
.
.
.
.
25.1.3 Die Klasse QGLFormat
.
.
.
.
.
.
25.1.4 Beispiel: Drehen eines Quaders in x-, y- und z-Richtung
25.1.5 Übung: Drehen einer Pyramide in x-, y- und z-Richtung
25.2 Qt-Programmierung mit Perl .
.
.
.
.
.
.
25.2.1 Ein erstes einfaches PerlQt-Beispiel
.
.
.
.
25.2.2 Kurze Beschreibung von PerlQt .
.
.
.
.
25.2.3 Beispiele zur PerlQt-Programmierung
.
.
.
25.3 Erstellen von Netscape Plugins
.
.
.
.
.
.
25.3.1 Herunterladen und Installieren des Plugin SDK
.
25.3.2 Die Qt Netscape-Plugin Erweiterung .
.
.
.
25.3.3 Kompilieren, Installieren und Testen von Plugins
.
25.3.4 Beispiele für mit Qt erstellte Netscape Plugins .
.
1079
1079
1080
1080
1081
1081
1084
1085
1085
1087
1092
1096
1096
1097
1102
1106
26 Der Qt GUI-Designer
26.1 Erstellen einer ersten einfachen Applikation mit dem Qt-Designer
26.2 Layout-Management im Qt-Designer
.
.
.
.
.
26.3 Ändern der Tab Order
.
.
.
.
.
.
.
.
26.4 Weitere GUI-Builder
.
.
.
.
.
.
.
.
1117
1117
1131
1139
1142
27 Erstellen von Qt-Programmen mit KDevelop
1143
28 Das Tool tmake
28.1 Allgemeines zu tmake
.
.
.
28.2 Installation von tmake
.
.
.
28.3 Einfache Benutzung von tmake
.
28.4 Konfiguration des Makefile
.
.
28.5 Variablen bei den einzelnen Templates
28.6 Setzen von Projektvariablen
.
.
28.7 Aufruf von tmake
.
.
.
.
28.8 Das Tool progen
.
.
.
.
XXII
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1149
1149
1149
1150
1151
1151
1152
1153
1154
Einleitung
Ursachen erkennen, das eben ist Denken, und dadurch
allein werden Empfindungen zu Erkenntnissen und
gehen nicht verloren, sondern werden wesenhaft und
beginnen auszustrahlen.
– Herrmann Hesse
Dieses Buch stellt die von der norwegischen Firma Trolltech entwickelte C ++-Klassenbibliothek Qt (Version 2.2) vor, die eine einfache und portable GUI-Programmierung ermöglicht. Mit Qt entwickelte Programme sind sofort ohne zusätzlichen Portierungsaufwand sowohl unter allen Unix- wie auch unter allen WindowsSystemen lauffähig. Sie müssen lediglich mit den entsprechenden Compilern (Visual C++ oder Borland C++ unter Windows-Systemen oder dem auf dem jeweiligen
Unix-System angebotenen cc-Compiler) kompiliert und gelinkt werden.
In Zukunft wird die Portabilität von entwickelter Software wohl immer wichtiger
werden, denn warum sollte man ein Programm entwickeln, das nur unter WindowsSystemen lauffähig ist, und sich damit freiwillig aus dem Markt der Millionen von
Unix- und Linux-Systemen ausschließen. Der umgekehrte Fall gilt selbstverständlich auch.
Es stellt sich hier natürlich die Frage, warum man bei Neuentwicklungen nicht
gleich die Programmiersprache Java verwenden sollte, die ebenfalls das Erstellen
portabler Programme ermöglicht. Nun, Java hat sicherlich wie Qt den Vorteil der
Portabilität, aber die Ablaufgeschwindigkeit von Java-Programmen kann nicht mit
der von Qt-Programmen mithalten. Außerdem sollte man berücksichtigen, dass Qt
eine C++-Bibliothek ist, und schon von Programmierern, die die Programmiersprache C beherrschen und nur grundlegende Kenntnisse in C++ besitzen, verwendet
werden kann. Und die Anzahl von Softwareentwicklern mit diesem Profil ist sehr,
sehr groß.
Voraussetzungen des Lesers
Ein gutes Beherrschen der Programmiersprache C wird in diesem Buch ebenso vorausgesetzt wie die Kenntnis der wesentlichen C-Standardfunktionen. Wie bei jedem fortgeschrittenen Programmierkurs kann auch hier ein Basiswissen über grundlegende
Datenstrukturen und Algorithmen nur von Vorteil sein.
1
Einleitung
Ein paar Worte zu diesem Buch
Bei einer so mächtigen Bibliothek wie Qt mit Hunderten von Klassen und Tausenden von Methoden, die zum Teil an Subklassen weitervererbt werden, stellt sich
natürlich die Frage, wie man so etwas vermitteln kann. Ein bloßes Vorstellen der
Klassen mit ihren Methoden und Datentypen wäre wenig sinnvoll, da der Neuling
zum einen von der Vielzahl der Informationen erschlagen würde und zum anderen
nicht das Zusammenspiel der einzelnen Klassen, was wohl für die Praxis mit am
wichtigsten ist, kennenlernen würde. Hier wurde daher folgende Vorgehensweise
gewählt:
❏ Vorstellen der wesentlichen Konstrukte, Klassen und Methoden von Qt
Es werden nicht alle Klassen, sondern nur die wesentlichen Klassen sowie dort
nur die wichtigsten Methoden vorgestellt. So soll vermieden werden, dass der
Leser sich durch die Vielzahl der Informationen überfordert fühlt. Eine vollständige Referenz zu Qt befindet sich in der bei der Qt-Software mitgelieferten Online-Dokumentation, ohne die auch erfahrene Qt-Programmierer kaum
auskommen.
❏ Zusammenfassen der Klassen zu funktionalen Themengebieten
Eine Beschreibung der Klassen in alphabetischer Reihenfolge würde dazu führen, dass der Leser die Klassen – ähnlich dem Lernen nach einem Lexikon –
nur unstrukturiert kennenlernen würde. Um dies zu vermeiden, ist dieses
Buch nach Themengebieten strukturiert, in denen jeweils die Klassen zusammengefasst sind, die artverwandt sind und Ähnliches leisten. Dieses didaktische Prinzip „Vom Problem (Aufgabenstellung) zur Lösung (Klasse)“ bringt
zwei Vorteile mit sich: Zum einen wird der Leser in einer strukturierten Form
an die mächtige Qt-Bibliothek herangeführt, und zum anderen ermöglicht dieser Aufbau ein schnelles Nachschlagen beim späteren praktischen Programmieren, wenn zu einer gewissen Aufgabenstellung entsprechende Informationen benötigt werden.
❏ Beispiele, Beispiele und noch mehr Beispiele
Um das Zusammenspiel der einzelnen Klassen und Methoden aufzuzeigen,
werden immer wieder Beispiele (über 250 Beispielprogramme mit etwa 30.000
Codezeilen) eingestreut, um typische Konstrukte oder Programmiertechniken
aufzuzeigen, die es ermöglichen, später beim selbstständigen Programmieren in diesen Beispielprogrammen nachzuschlagen, wenn ähnliche Problemstellungen vorliegen. Es sei an dieser Stelle darauf hingewiesen, dass sich
so bisweilen auch umfangreichere Programmlistings ergeben, die vielleicht
zunächst etwas abschreckend wirken; aber praxisnahes Programmieren, das
durch dieses Buch vermittelt werden soll, hat eben selten etwas mit „ZwanzigZeilern“ zu tun. Um diese Listings nicht allzu groß werden zu lassen, werden
die Methoden oft inline definiert, was hoffentlich verziehen wird.
❏ Übungen am Ende der Kapitel
Um den Leser seine in einem Kapitel erworbenen Kenntnisse selbst testen zu
lassen, befinden sich am Ende nahezu jeden Kapitels Übungsprogramme, die
teilweise sehr anspruchsvoll sind. Bei einigen dieser nahezu 100 Übungspro-
2
Einleitung
gramme (mit über 10.000 Codezeilen) muss der Leser eventuell in der QtOnline-Dokumentation nachschlagen, um die Aufgabenstellungen zu lösen.
Dies ist beabsichtigt, da man in der späteren Programmierpraxis auch selbstständig arbeiten muss und kaum ohne ein Nachschlagen in der Qt-OnlineDokumentation auskommen wird.
Übersicht über dieses Buch
Das Buch gliedert sich in folgende Teile:
Kapitel 1 gibt eine kurze Einführung in die Welt der Objektorientierung und insbesondere in die wichtigsten Konzepte der objektorientierten Sprache C ++,
da solche grundlegenden Kenntnisse für eine Programmierung mit der objektorientierten C++-Klassenbibliothek erforderlich sind. Leser, die mit der
Objektorientierung und C++ vertraut sind, können dieses Kapitel übergehen
und unmittelbar mit Kapitel 2 fortfahren.
Kapitel 2 klärt zunächst einmal, was Qt überhaupt ist und welche Vorteile es aufweist, bevor der wichtige Qt-Begriff „Widget“ eingeführt wird. Die folgenden
Absätze gehen dann kurz auf die bei Qt mitgelieferte Dokumentation ein, bevor abschließend auf die Generierung von Qt-Programmen mit make sowie
mit dem eigens von den Qt-Entwicklern angebotenen Tool tmake zur automatischen Erstellung von Makefiles eingegangen wird.
Kapitel 3 gibt dann anhand von Beispielen einen Überblick über die wesentlichen
Konzepte und Konstrukte von Qt. Es zeigt zunächst den grundsätzlichen
Aufbau eines Qt-Programms, bevor es das wichtige Signal-Slot-Konzept von
Qt detaillierter vorstellt. Ebenso wird in diesem Kapitel die Klasse QString
vorgestellt, welche eine Abstraktion zu Unicode-Text und zum String-Konzept im klassischen C ist. Ein eigener Abschnitt stellt dann die von Qt verwendeten Farbmodelle vor und klärt, was Farbgruppen sind und wie Farbpaletten für Widgets geändert werden können. Im letzten, etwas umfangreicheren Abschnitt dieses Kapitels wird schließlich ein kleines Malprogramm zum
Zeichnen mit der Maus auf dem Bildschirm erstellt, das schrittweise immer
mehr erweitert wird, indem Menüs und Laufbalken hinzugefügt werden. In
seiner letzten Version ist es sogar möglich, die gemalten Bilder zu speichern
und wieder neu zu laden.
Kapitel 4 gibt einen Überblick über die wichtigsten von Qt angebotenen Widgets.
Die einzelnen Widgets sind in diesem Kapitel nach Themengebieten organisiert, in denen jeweils die Klassen zusammengefasst sind, die artverwandt
sind und Ähnliches leisten.
Kapitel 5 zeigt die unterschiedlichen Möglichkeiten des Layout und der Zuordnung von Widgets, wie sie von Qt angeboten werden.
Kapitel 6 beschreibt die von Qt vordefinierten Dialogfenster, die für typische Kommunikationen mit dem Benutzer, wie z. B. Auswahl einer bestimmten Farbe
3
Einleitung
oder einer Datei, ausgelegt sind. Diese vordefinierten Dialogfenster nehmen
dem Qt-Programmierer viel Arbeit ab, da sie schon mit entsprechenden Auswahlmöglichkeiten und/oder Buttons versehen sind.
Kapitel 7 stellt dann die von Qt angebotenen Klassen für Datei- und VerzeichnisOperationen vor, die nicht nur plattformunabhängig, sondern auch einfach
zu verwenden sind.
Kapitel 8 stellt zunächst die von Qt vordefinierten Datentypen (Klassen) QPoint,
QSize und QRect vor, die vor allen Dingen beim Zeichnen geometrischer
Objekte in einer Malfläche benötigt werden. Bevor dieses Kapitel dann mit
der detaillierteren Beschreibung der einzelnen von Qt angebotenen TemplateKlassen für typische Datenstrukturen wie z. B. Arrays oder Listen beginnt,
stellt es zunächst nochmals kurz grundlegende Konzepte von C ++ vor, die für
das Verständnis der nachfolgenden Abschnitte notwendig sind. Dabei werden zunächst Konzepte wie „explizites und implizites Sharing“ oder „tiefe
Kopie“ (deep copy) und „flache Kopie“ (shallow copy) geklärt, bevor die entsprechenden Template-Klassen und Methoden aufgezählt werden, die das jeweilige Konzept verwenden.
Kapitel 9 zeigt, wie unterschiedliche Applikationen direkt untereinander Daten unter Verwendung des global verfügbaren Clipboard bzw. mittels der Drag-andDrop-Technik austauschen können.
Kapitel 10 stellt Klassen vor, mit denen man Datums- und Zeitoperationen durchführen oder sich aber auch Zeitschaltuhren (Timer) einrichten kann, die in
festgelegten Zeitperioden immer wieder Signale an das eigene Programm
schicken.
Kapitel 11 stellt zunächst die Möglichkeiten der Farballozierung mit Qt vor, bevor
es sich tiefergehend mit den mächtigen Grafik-Klassen von Qt beschäftigt,
die alles zeichnen lassen, von einfachen Linien bis zu komplexen Figuren wie
Kuchenstücke oder andere geometrische Figuren. Daneben zeigt dieses umfangreichere Kapitel, wie Grafiken mit Qt auch transformiert, z. B. vergrößert
oder gedreht werden können. Ein eigenes Unterkapitel stellt dann noch einige Techniken vor, mit denen man Flimmern beim Neuzeichnen eines Bildes vermeiden oder zumindest reduzieren kann. Der letzte Abschnitt stellt
schließlich noch die QCanvas-Klassen vor, mit denen Qt einen weiteren Satz
von Klassen für zweidimensionale Grafiken zur Verfügung stellt. Diese erlauben es, grafische Elemente schneller zeichnen zu lassen, und sie benötigen
auch wenig Speicher. Neben weiteren Vorteilen erlauben diese Klassen auch
mehrere Ansichten der gleichen Grafikfläche.
Kapitel 12 stellt die von Qt unterstützen Bildformate und Cursorformen vor. Dazu
geht es zunächst auf die Pixmap-Klassen ein, die für Zeichnungen ausgelegt
und optimiert sind. Im nächsten Abschnitt wird dann die Klasse QCursor behandelt, mit der man dem Mauscursor ein spezielles Aussehen geben kann.
Der dritte Abschnitt stellt mit der Klasse QImage die zweite Klasse neben
4
Einleitung
den Pixmap-Klassen vor, die von Qt für die Bildbearbeitung angeboten wird.
Während die Pixmap-Klassen für Zeichnungen ausgelegt und optimiert sind,
ist die Klasse QImage für E/A, direkte Pixel-Zugriffe und -Manipulationen
geeignet, da sie ein hardwareunabhängiges Pixmap-Format verwendet. Im
letzten Abschnitt dieses Kapitels wird noch die Klasse QPicture vorgestellt,
die es ermöglicht, Mal-Kommandos aufzuzeichnen und später wieder ausführen zu lassen.
Kapitel 13 geht auf Animationen und Sounds ein und zeigt, wie man mit den eigenen von Qt angebotenen Klassen animierte Bilder oder eben Sound-Dateien
abspielen kann.
Kapitel 14 zeigt zunächst, wie man falsche Benutzereingaben verhindern kann, bevor es die von Qt unterstützten regulären Ausdrücke vorstellt.
Kapitel 15 behandelt den Tastaturfokus, der immer nur auf ein Eingabeelement
eingestellt sein kann. Den Tastaturfokus besitzt immer das Eingabeelement,
das gerade Eingaben von der Tastatur entgegennehmen kann. Der Tastatur
Tab -Taste auf das nächste Eingabeelement
fokus kann üblicherweise mit der Tab -Taste bei gleichzeitig gedrückter Shift -Taste auf das vorbzw. mit der herige Eingabeelement verschoben werden. Ebenso kann man üblicherweise
den Tastaturfokus direkt auf ein Eingabeelement einstellen, indem man auf
dieses mit der Maustaste klickt.
Kapitel 16 erläutert zunächst einmal die grundsätzliche Vorgehensweise von Qt
beim Auftreten von Events, bevor es im nächsten Abschnitt die Basisklasse
QEvent und alle von ihr abgeleiteten Event-Klassen vorstellt. Der nächste
Abschnitt behandelt dann so genannte „Event-Filter“. Ein Event-Filter ist ein
Objekt, das alle Events für andere Objekte empfängt. Dieses Objekt kann
dann entscheiden, ob es auf die empfangenen Events selbst reagiert und/oder
die empfangenen Events an die entsprechenden anderen Objekte weiterleitet
oder nicht. In den beiden letzten Abschnitten dieses Kapitels wird dann das
Senden eigener Events und die Bearbeitung benutzerdefinierter Events vorgestellt.
Kapitel 17 stellt das „Signal-Slot-Konzept“, das zwar bereits zu Beginn kurz beschrieben und in den Beispielen der vorherigen Kapitel auch ständig verwendet wurde, nochmals vollständig vor, wobei es auch einige bisher noch nicht
behandelte Aspekte des Signal-Slot-Konzepts zeigt.
Kapitel 18 zeigt, wie man sich eigene Widget-Klassen erstellen kann. Dazu stellt
dieses Kapitel zunächst einige wichtige Punkte vor, die dabei zu beachten
sind, bevor es anhand von zwei umfangreicheren Beispielen (Funktionsplotter und Tabelle von Bildern) das Erstellen eigener Widgets verdeutlicht.
Kapitel 19 stellt zunächst die von Qt angebotene plattformunabhängige ThreadProgrammierung und -Synchronisation vor. Dazu stellt es zunächst die für
Threads zu verwendende Klasse QThread vor, bevor es Klassen vorstellt, mit
denen gleichzeitige laufende Threads synchronisiert werden können.
5
Einleitung
Kapitel 20 zeigt, wie man mehrsprachige und international verwendbare Qt-Programme erstellen kann. So entwickelte Qt-Applikationen lassen sich leicht
und ohne viel Aufwand an länder- und kulturspezifische Gegebenheiten anpassen, so dass der Benutzer dieser Applikation entsprechend seinen Gewohnheiten die entsprechende Sprache, Zeichenkodierung und -darstellung
verwenden kann.
Kapitel 21 stellt zum einen Funktionen und Makros vor, mit denen man in einem
Programm Testausgaben und automatische Verifizierungen einbauen kann.
Zum anderen zeigt es, wie man Qt-Objekte mit Namen versehen kann, um
sich dann beim Programmablauf mittels eigens dafür konzipierten Qt-Funktionen Debug-Informationen ausgeben zu lassen.
Kapitel 22 stellt die drei unterschiedlichen Typen von Klassen vor, mit denen man
leicht und portabel Netzwerkprogrammierung durchführen kann. Der erste
Typ von Netzwerk-Klassen, der in diesem Kapitel vorgestellt wird, ist eher
passiver Art. Zu dieser Art gehören unter anderem die beiden Klassen QUrl
und QUrlOperator, mit denen man URLs (Uniform Resource Locator) protokollunabhängig bearbeiten kann. Danach stellt dieses Kapitel die Klasse
QNetworkProtocol vor, die eine abstrakte Ebene zur Verfügung stellt, auf
der man eigene Netzwerkprotokolle implementieren kann. Die Klasse QUrlOperator ermöglicht dann ein Arbeiten mit solchen selbstdefinierten Netzwerkprotokollen. Im letzten Teil dieses Kapitels wird dann auf Klassen wie
QSocket, QServerSocket, QDns, QFtp usw. eingegangen, die ein portables
Arbeiten mit TCP/IP-Sockets ermöglichen.
Kapitel 23 zeigt, wie man blockierungsfrei Daten im Hintergrund übertragen kann,
denn das Schreiben in oder das Lesen aus Dateien kann bei großen Datenmengen eine sehr zeitaufwendige Operation sein, in der das ganze Programm
blockiert ist, so dass der Benutzer in dieser Zeit nicht weiter mit der Applikation arbeiten kann. Qt bietet für solche Situationen abstrakte Klassen, die eine
Übertragung von Daten im Hintergrund durchführen lassen. Diese Klassen
werden in diesem Kapitel beschrieben.
Kapitel 24 behandelt das XML-Modul von Qt, das einen XML-Parser mit einer
SAX2- (Simple API for XML) Schnittstelle und eine Implementierung des DOM
Level 1 (Document Object Model) zur Verfügung stellt. SAX2 ist eine sehr
beliebte Java-Schnittstelle für XML-Parser, und DOM Level 1 ist eine W3CEmpfehlung für XML-Schnittstellen.
Kapitel 25 stellt von der Vielzahl der zwischenzeitlich entwickelten Qt-Schnittstellen zu anderen Bibliotheken und Sprachen drei der wichtigsten kurz vor:
OpenGL-Programmierung mit Qt, Perl-Programmierung mit Qt und Erstellen von Netscape-Plugins mit Qt.
Kapitel 26 stellt den Qt GUI-Designer vor, der ein visuelles Design-Tool ist, das
das Entwerfen und Implementieren grafischer Benutzerschnittstellen erheblich vereinfacht. Dieses Kapitel gibt anhand von Beispielen eine kurze Einführung in den bei Qt mitgelieferten Qt-Designer.
6
Einleitung
Kapitel 27 stellt die im Rahmen des KDE-Projekts1 entwickelte Entwicklungsumgebung KDevelop kurz vor. KDevelop erleichtert das Erstellen von GUI-Programmen ganz wesentlich und spart Zeit durch Automatisierung von StandardEntwicklungsprozessen, genauso wie es einen direkten und transparenten
Zugriff auf alle Informationen bietet, die man benötigt.
Kapitel 28 beschreibt das von der Firma Trolltech bereitgestellte Tool tmake, mit
dem man sich automatisch Makefiles aus seinen Qt-Quellprogrammen generieren lassen kann.
Beispiel- und Übungsprogramme auf der CD
Alle Programmbeispiele und Übungsprogramme dieses Buches befinden sich auf
der in diesem Buch enthaltenen CD.
Für Linux/Unix existiert auch ein eigener Browser, um alle Programmlistings interaktiv zu lesen bzw. diese Programme auch über diesen Browser zu starten; siehe
dazu auch Abbildung 1. Um diesen Browser zu starten, müssen Sie nur in das Directory wechseln, in dem Sie die CD gemountet haben und dann qtbuch aufrufen.
Noch ein kurzer Hinweis: Sollte Sie der tanzende Pinguin stören, bewegen Sie den
Mauscursor auf ihn und warten Sie ein wenig, bis ein Tooltip eingeblendet wird.
Das Lizenzmodell von Trolltech
Trolltechs Lizenzmodell ist eigentlich relativ einfach, auch wenn es immer wieder
für Verwirrung sorgt.
In erster Linie ist Qt als kommerzielle Software erhältlich, derzeit für die drei Plattformen Unix/X11, MS-Windows und Linux/Embedded. An Unterstützung für
weitere Plattformen – z.B. Mac OS X – wird gearbeitet.
Als kommerzieller Lizenznehmer der Desktop-Verion von Qt erhalten Sie
❏ die Qt-Bibliothek mit vollständigem Quellcode
❏ eine persönliche Lizenz um kommerzielle Anwendungen mit Qt entwickeln
zu können
❏ ein Jahr freie Upgrades auf alle neuen Versionen von Qt
❏ ein Jahr E-Mail-Support
❏ die vollständige Referenz Dokumentation
Es gibt keine Royalties, Run-Time-Lizenzen oder weitere Kosten, d. h. Sie können
ohne weiteres Qt-basierte Anwendungen statisch oder dynamisch gelinked vertreiben.
Derzeit werden zwei verschiedene Editionen angeboten:
❏ die Professional Edition und die
❏ Enterprise Edition
1 KDE
ist die Abkürzung für „K Desktop Environment“ (siehe auch http://www.kde.org).
7
Einleitung
Abbildung 1: Der Browser für die Beispiel- und Übungsprogramme (unter Linux/Unix)
Unterschiede liegen im Umfang und Preis. Als Preisbeispiel kostet die Dual-Pack
Enterprise Edition für 6 Entwickler für sowohl MS-Windows als auch Unix/X11 pro
Entwickler 2 490 USD (Stand Juni 2001). Im Preis enthalten sind ein Jahr Upgrades
und technischen Support.
Mit dieser Preisstruktur befindet sich Trolltech deutlich im unteren Preissegement
bei C/cppMultiplattform-Lösungen, aber eben auch über dem gewöhnlichen Budget von Privatanwendern oder Studenten.
Fuer Universitäten hat Trolltech deshalb das Qt Educational Program ins Leben
gerufen, dass es ermöglicht, für Ausbildungszwecke kostenlose Site-Lizenzen für
Qt zu erwerben.
Privatleute haben die Möglichkeit, kostenlos die Qt NonCommercial Edition auszuprobieren und damit geschriebene Programme als freie Software zu vertreiben.
Und last but not least: Für Benutzer Freier bzw. Open-Source Betriebsysteme wie
Linux oder FreeBSD, die Freie bzw. Open-Source Software mit Qt schreiben wollen,
gibt es die Qt Free Edition, die unter den Open-Source Lizenzen QPL und GNU
GPL vertrieben wird. Freie bzw. Open-Source Software bedeutet nicht nur, dass
diese Software in der Regel umsonst ist. Alle Anwender der Software müssen den
8
Einleitung
komplette Quellcode umsonst bekommen können, einschliesslich des Rechts, die
Software verändert oder unverändert weitervertreiben zu dürfen.
Wichtig: Wenn Sie kommerzielle bzw. proprietäre Software mit Qt entwickeln –
auch unter Linux – brauchen sie eine kommerzielle Qt Lizenz. Im Zweifelsfall fragen Sie am besten einfach [email protected].
9
Einleitung
10
Kapitel 1
Einführung in die
Objektorientierung und C++
Kunst ist die rechte Hand der Natur.
Diese hat nur Geschöpfe, jene hat Menschen gemacht.
– F. Schiller
Da Qt eine objektorientierte C++-Klassenbibliothek ist, wird hier eine kurze Einführung in die Welt der Objektorientierung und insbesondere in die wichtigsten
Konzepte der objektorientierten Sprache C++ gegeben. Leser, die mit der Objektorientierung und C++ vertraut sind, können dieses Kapitel übergehen und unmittelbar mit Kapitel 2 fortfahren.
Zunächst zeigt dieses Kapitel, dass auch die Natur, in der wir leben, objektorientiert
ist, bevor es die wesentlichen Aspekte vorstellt, welche die objektorientierte von
der traditionellen (funktionalen) Softwareentwicklung unterscheiden. Da C ++ eine Erweiterung der weitverbreiteten prozeduralen Sprache C ist, werden anschließend die Erweiterungen von C++ vorgestellt, die zwar sehr nützlich sind und ein
eleganteres Programmieren in C zulassen, aber C++ noch nicht zu einer objektorientierten Sprache befähigen. Abschließend werden dann die wesentlichen neuen
Sprachelemente vorgestellt, die C++ zu einer objektorientierten Sprache machen.
1.1
Objektorientierung in der realen Welt
In der Welt, in der wir leben, sind wir von unzähligen Dingen (Objekten) mit
verschiedenen Eigenschaften umgeben. Aufgrund dieser Eigenschaften sowie der
Möglichkeiten, mit diesen Eigenschaften umzugehen oder von ihnen beeinflusst zu
werden, kann man unterschiedliche Objekte zu Klassen zusammenfassen. Ein sehr
schönes Beispiel hierfür liefert uns die Natur. Betrachten wir einen Ausschnitt aus
der Welt der Lebewesen.
Der Begriff „Lebewesen“ beschreibt umfassend alle möglichen (uns bekannten) Lebensformen auf unserem Planeten. Dahinter verbergen sich jedoch verschiedene
Gruppen. So unterscheidet man z. B. „Pflanze“ und „Tier“. Diese Gruppen (Unter-
11
1 Einführung in die Objektorientierung und C++
L e b e w e s e n
P fla n z e
B a u m
T ie r
S ä u g e tie r
B lu m e
M e n s c h
F is c h
K a tz e
H a u s k a tz e
T ig e r
Abbildung 1.1: Einteilung von Lebewesen
klassen) kann man aufgrund unterschiedlicher Eigenschaften wiederum unterteilen (Tier: „Säugetier“, „Fisch“ etc.). Es sind dann weitere Differenzierungen möglich (Säugetier: „Mensch“, „Katze“ etc.), wobei auch diese Spezialisierungen weitere Unterteilungen zulassen, wie in Abbildung 1.1 gezeigt ist.
Ordnet man jedem dieser Kästen aus Abbildung 1.1 bestimmte Eigenschaften zu,
so erkennt man, dass die Anzahl der Eigenschaften von oben nach unten zunimmt.
Der obersten Klasse („Lebewesen“) kann man nur die Eigenschaft „lebendig“ zuordnen. Gehen wir eine Stufe tiefer und betrachten die Gruppe „Tier“, die wieder
alle gewisse Eigenschaften – wie z. B. „bewegungsfähig“ – gemeinsam haben, während die Gruppe „Pflanzen“ andere Charakteristika aufweist. Entscheidend ist,
dass beide Gruppen, sowohl „Tiere“ als auch „Pflanzen“, die Eigenschaft „lebendig“ von der ihr übergeordneten Klasse „Lebewesen“ erben. Begeben wir uns noch
weiter nach unten, so werden wir auf immer mehr (neue) Eigenschaften stoßen. Die
Besonderheit liegt darin, dass eine Unterklasse sämtliche Eigenschaften der übergeordneten Klasse übernimmt (erbt). So ist letztendlich die genaue Beschreibung
eines bestimmten Lebewesens möglich.
Solange wir nur die Beschreibung eines bestimmten Lebewesens betrachten, sprechen wir also von Klasse. Nun gibt es aber von jeder möglichen untergeordneten
Lebewesen-Klasse mehr oder weniger viele Vertreter (Exemplare). Hier sprechen
wir dann von einem Objekt (auch als Instanz bezeichnet), das alle Eigenschaften der
entsprechenden Klasse besitzt. So ist z. B. ein Tiger namens „Saimura“ in einem
bestimmten Zoo ein Objekt (eine Instanz) der Klasse „Tiger“, die von der Klasse
„Katze“ abgeleitet wurde, welche wiederum „Säugetier“ als Basisklasse hat usw.
Allgemein gilt also, dass die in der realen Welt vorkommenden Elemente immer
spezifischere Eigenschaften aufweisen, je tiefer sie sich in einer entsprechenden
12
1.1 Objektorientierung in der realen Welt
Abbildung 1.2: Objekte (Exemplare) zur Klasse Tiger
Baumhierarchie (wie sie z. B. in Abbildung 1.1 gezeigt) befinden. Bei gleichartigen Objekten wird also nicht jedes einzelne Objekt für sich beschrieben, sondern
es wird eine allgemeine Beschreibung (Klasse) für diesen Typ von Objekten gegeben. Mit Hilfe solcher Beschreibungen lassen sich dann die konkreten Objekte den
jeweiligen Klassen zuordnen. Jedes individuelle Objekt ist dann ein Exemplar der
entsprechenden Klasse (siehe auch Abbildung 1.2).
Die Tiger „Samurai“, „Taigon“ und „Rufus“ in Abbildung 1.2 sind alle Exemplare
(Instanzen, Objekte) der Klasse „Tiger“. Es ist offensichtlich, dass die Klasse „Tiger“
kein eigenes Objekt ist, sondern eben nur eine Beschreibung.
In den nachfolgenden Abbildungen werden Klassen und Objekte nach der Notation der Unified Modeling Language (UML) dargestellt, d. h. als Rechtecke. Zur Unterscheidung von Klassen und Objekten wird bei Objekten der Name unterstrichen:
O b je k t
K la s s e
Abbildung 1.3: Objekt und Klasse in der UML-Notation
Wenn man die Objekt-Klassen-Beziehung (Exemplarbeziehung, Instanzbeziehung)
darstellen möchte, wird zwischen einem Objekt und seiner Klasse ein gestrichelter
Pfeil in Richtung der Klasse gezeichnet:
K la s s e
< in s ta n c e o f>
O b je k t
Abbildung 1.4: Objekt-Klassen-Beziehung
Im Falle des Tigers „Samurai“ sagt man dann: „Samurai ist ein Exemplar der Klasse
Tiger“ oder „Samurai ist eine Instanz der Klasse Tiger“:
13
1 Einführung in die Objektorientierung und C++
< in s ta n c e o f>
T ig e r
S a m u ra i
Abbildung 1.5: Beispiel einer Objekt-Klassen-Beziehung
Die Objektorientierte Programmierung (OOP) stützt sich auf diese Denkweise. Es
besteht die Möglichkeit, Klassen zu definieren und ihre Eigenschaften an Unterklassen zu vererben, um letztendlich die genaue Beschreibung eines bestimmten
Sachverhalts zu erreichen. Ausgehend von dieser nun erhaltenen Beschreibung,
können Objekte (Instanzvariable) deklariert/definiert werden, die letztendlich eine greifbare Repräsentation der jeweiligen Beschreibung darstellen.
1.2
Objektorientierung in der Software
In diesem Kapitel werden die wesentlichen Konzepte vorgestellt, welche die objektorientierte Softwareentwicklung von der traditionellen (funktionalen) Softwareentwicklung unterscheiden.
Schritt 1: Zusammenfügen von Daten und Funktionen
Der erste Schritt zur Übernahme der Objektorientierung in die Softwareentwicklung war, dass man Daten und Funktionen, die in der funktionalen Softwareentwicklung noch als getrennte Einheiten nebeneinander standen, zu einer Einheit zusammenfügte, wie dies Abbildung 1.6 verdeutlicht.
Hierbei lag die Idee des „Füge zusammen, was zusammengehört“ zugrunde. Man
beseitigte damit einen ersten großen Nachteil von nicht objektorientierten Programmen, die keinen direkten Bezug zwischen Daten und den Funktionen, die auf diese
Daten lesend oder schreibend zugriffen, direkt erkennen ließen.
Wie leicht aus Abbildung 1.6 zu erkennen ist, verschmelzen bei der Objektorientierten Programmierung die Daten und die (diese Daten bearbeitenden) Funktionen zu
einer Einheit, wodurch eine klare, eindeutige und überschaubare Softwarestruktur
K la s s is c h e ( fu n k tio n a le ) S o ftw a r e e n tw ic k lu n g
D a te n
D a te n
V a r ia b le x
F u n k tio n 1
O b je k to r ie n tie r te S o ftw a r e e n tw ic k lu n g
V a r ia b le y
F u n k tio n 2
F u n k tio n 3
V a r ia b le 1
V a r ia b le b
V a r ia b le 2
F u n k tio n x
V a r ia b le 3
F u n k tio n y
F u n k tio n i
F u n k tio n z
F u n k tio n x
Abbildung 1.6: Klassische und objektorientierte Programmierung
14
D a te n
V a r ia b le a
1.2 Objektorientierung in der Software
K la s s is c h e ( fu n k tio n a le ) S o ftw a r e e n tw ic k lu n g
D a t e n ( n a c h a u ß e n h in g e s c h ü tz t)
D a te n
V a r ia b le a
V a r ia b le x
U n k o n tr o llie r te r
Z u g r iff m ö g lic h
F u n k tio n 1
O b je k to r ie n tie r te S o ftw a r e e n tw ic k lu n g
F r e m d fu n k tio n
V a r ia b le b
U n k o n tr o llie r te r
Z u g r iff n ic h t m ö g lic h
F u n k tio n x
F r e m d fu n k tio n
F u n k tio n y
F u n k tio n z
Abbildung 1.7: Zugriffsschutz bei der Objektorientierten Programmierung
erreicht wird. Es lässt sich auf einen Blick erkennen, welche Daten durch welche
Funktionen bearbeitet (verändert) werden.
Schritt 2: Information Hiding
Ein zweiter großer Nachteil der klassischen funktionalen Programmierung ist ihr
mangelndes Schutzkonzept, da sie einen ungeschützten (meist auch ungewollten)
Zugriff „fremder“ Funktionen auf Daten zulässt.
Um diesen Nachteil zu beseitigen, woraus oft schwer auffindbare Fehler resultierten, führte die Objektorientierung ihr eigenes Schutzkonzept ein, indem sie Möglichkeiten anbietet, Daten und Funktionen einer Klasse verschiedenen Schutzgraden (privat: nur innerhalb der Klasse ansprechbar; öffentlich: auch außerhalb der
Klasse zugänglich) zuzuordnen. So können bei entsprechender Definition die Daten einer Klasse nur über die vom Programmierer zur Verfügung gestellten Funktionen verändert werden. Ein unkontrollierter Zugriff durch Fremdfunktionen wird
somit verhindert. Abbildung 1.7 verdeutlicht diesen Sachverhalt. Diese Abbildung
zeigt auch, dass ein Zugriff auf die geschützten Daten niemals direkt, sondern nur
durch die nach außen sichtbaren Funktionen möglich ist.
Schritt 3: Verwendung bereits vorhandener Software
Wie bereits angesprochen, werden in der Objektorientierten Programmierung Objekte aufgrund vorliegender Klassendefinitionen gebildet. Somit besteht die Möglichkeit, Klassendefinitionen für oft benötigte Sachverhalte in so genannten „Klassenbibliotheken“ zu hinterlegen. Durch einfaches Übernehmen dieser Definitionen
(und eventuelles Hinzufügen neuer Teile mit Hilfe des Vererbungsmechanismus)
wird die Softwareentwicklung stark vereinfacht. Man spricht auch von Softwareentwicklung durch Reproduktion (Nachbildung) von Objektbeschreibungen (Klassendefinitionen).
15
1 Einführung in die Objektorientierung und C++
1.3
Nicht-objektorientierte Erweiterungen in C++
Da C++ eine Erweiterung der weitverbreiteten prozeduralen Sprache C ist, werden
hier zunächst die Erweiterungen von C++ vorgestellt.
1.3.1 Zeilen-Kommentare mit //
Neben dem C-Kommentar, der innerhalb des Codes mit der Zeichenfolge /* eingeleitet und mit der Zeichenfolge */ beendet wird, bietet C++ zusätzlich noch die
Zeichenfolge // zum Kommentieren an: Alle Zeichen ab // bis zum Zeilenende
werden als Kommentar interpretiert.
double epsilon; /* C-Kommentar, der sich über
meherere Zeilen erstrecken kann und
auch in C++ weiterhin verwendet werden kann.
*/
double epsilon; // Ab hier bis Zeilenende Kommentar (nur in C++ mögl.)
1.3.2 Variablen-Deklarationen (auch im Anweisungsteil)
In C war es vorgeschrieben, dass Variable nur entweder global oder am Anfang
eines durch { } gekennzeichneten Blockes deklariert werden durften. VariablenDeklarationen an beliebigen Stellen innerhalb des Anweisungsteils waren nicht erlaubt. In C++ können nun Variablen-Deklarationen an jeder beliebigen Stelle im
Code erfolgen. Die Lebensdauer der deklarierten Variablen beschränkt sich dabei
(wie auch in C) auf den Block, in dem sie deklariert wurden:
void function()
{
........
// ......
printf("C-Anweisungen");
// beliebige C/C++-Anweisungen
........
// ......
int z = 5;
// Deklaration der Variablen ’z’
// Diese Variable ist nur innerhalb der
.........
// Funktion function() bekannt
}
int main(void)
{
........
// ......
printf ("C-Anweisungen");
// beliebige C/C++-Anweisung
........
// ......
for (int i = 1; i < 10; i++) {
......
}
return 0;
}
16
// Deklaration der Variablen ’i’
// Diese Variable ist innerhalb
// der Funktion main bekannt
1.3 Nicht-objektorientierte Erweiterungen in C++
1.3.3 Default-Argumente bei Funktionsaufrufen
Es gibt Anwendungsfälle, bei denen nicht alle bei einer Funktionsdeklaration angegebenen Parameter bei jedem Aufruf wirklich benötigt werden. In solchen Fällen muss man in C beim Aufruf trotzdem für jeden Parameter ein entsprechendes
Argument (Dummy-Argument) angeben. Nehmen wir z. B. eine Funktion add_bis4(), die bis zu vier ganze Zahlen (als Argumente anzugeben) addieren kann
und das Ergebnis zurückgibt.
int add_bis4(int z1, int z2, int z3, int z4) {
return(z1+z2+z3+z4);
}
Will man in C nun nur zwei Zahlen durch diese Funktion addieren lassen, muss
man trotzdem alle vier Argumente angeben:
ergeb = add_bis4(25, 43, 0, 0);
/* in C: Dummy-Argumente 0, 0 */
C++ bietet nun für solche Fälle so genannte Default-Argumente an, die man den
Parametern bei der Deklaration/Implementierung einer Funktion zuweisen kann,
wie z. B.:
int add_bis4(int z1, int z2=0, int z3=0, int z4=0) {
return(z1+z2+z3+z4);
}
Gibt der Aufrufer der Funktion das jeweilige Default-Argument nicht an, so wird
dieses Argument automatisch mit seinem Default-Wert belegt:
ergeb = add_bis4(25, 43);
// entspr.: ergeb = add_bis4(25, 43, 0, 0);
ergeb = add_bis4(7, 4, -8); // entspr.: ergeb = add_bis4(7, 4, -8, 0);
ergeb = add_bis4(53);
// entspr.: ergeb = add_bis4(53, 0, 0, 0);
Default-Argumente werden oft auch dazu verwendet, um für eine Funktion ein
bestimmtes Standardverhalten vorzugeben. Werden beim Aufruf dieser Funktion keine Argumente für die optionalen Default-Argumente angegeben, so verhält
sich die Funktion entsprechend ihrem festgelegten Standard. Möchte der Aufrufer
aber die Funktion abweichend von ihrer Standardvorgabe ausführen lassen, kann
er dies über die Angabe eigener Argumente (für die Default-Argumente) steuern.
Nachfolgend ist hierzu ein Beispiel gegeben.
void kostrech(double einnahme, double ausgabe,
char *waehrung="EUR", double factor=1.0) {
double gewinn = einnahme - ausgabe;
printf("Einnahme: %.2f %s (%.2f EUR)\n",
einnahme, waehrung, einnahme*factor);
printf("Ausgabe : %.2f %s (%.2f EUR)\n",
ausgabe,
waehrung, ausgabe*factor);
printf("------------------------------------\n");
printf("Gewinn
: %.2f %s (%.2f EUR)\n", gewinn,
waehrung, gewinn*factor);
}
Für diese Funktion sind nun z. B. folgende Aufrufe möglich:
17
1 Einführung in die Objektorientierung und C++
kostrech(1370.34, 1250.76);
// Standardverhalten
// Ausgabe bei diesem Aufruf: Einnahme: 1370.34 EUR (1370.34 EUR)
//
Ausgabe : 1250.76 EUR (1250.76 EUR)
//
------------------------------------
//
Gewinn
: 119.58 EUR (119.58 EUR)
kostrech(1800.0, 2500.0, "YEN", 0.0095);
// Ausgabe bei diesem Aufruf:
Einnahme: 1800.00 YEN (17.10 EUR)
//
Ausgabe : 2500.00 YEN (23.75 EUR)
//
------------------------------------
//
Gewinn
: -700.00 YEN (-6.65 EUR)
kostrech(23487.40, 21345.7, "USD", 1.02);
// Ausgabe bei diesem Aufruf:
Einnahme: 23487.40 USD (23957.15 EUR)
//
Ausgabe : 21345.70 USD (21772.61 EUR)
//
//
-----------------------------------Gewinn : 2141.70 USD (2184.53 EUR)
Es ist zu beachten, dass Default-Argumente immer nur für die „hinteren“ (am weitesten rechts stehenden) Parameter innerhalb der Schnittstelle erlaubt sind. Würde
beim Aufruf einer Funktion mit Default-Argumenten ein mittleres Argument weggelassen werden, wäre es dem Compiler nicht möglich herauszufinden, welcher
Parameter entfallen ist. Demzufolge könnte er auch die nachfolgenden Argumente
nicht richtig zuordnen. Dazu folgendes Beispiel:
void f1(int a, int b, int c = 0);
// erlaubt
void f2(int a, int b = 0, int c = 0);
// erlaubt
void f3(int a, int b = 0, int c);
// NICHT erlaubt
Im Folgenden sind alle möglichen Aufrufformen dieser hier deklarierten Funktionen gezeigt:
f1( 1, 2, 3);
// Alle Argumente angegeben
f1( 1, 2);
// 3. Default-Argument weggelassen
f2( 4, 5, 6);
// Alle Argumente angegeben
f2( 4, 5);
// 3. Default-Argument weggelassen
f2( 4);
// 2. Und 3. Default-Argument weggelassen
// f3() - Aufruf nicht möglich, da Definition syntaktisch falsch
Default-Argumente dürfen nur im Prototyp, nicht aber bei der Definition einer
Funktion angegeben werden.
1.3.4 Überladen von Funktionen
Es besteht oft der Wunsch, für ähnliche, aber doch unterschiedliche Aufgaben Funktionsaufrufe mit gleichem Namen verwenden zu können. Anwendungsfälle und
mögliche Lösungen hierfür wurden bereits im vorigen Kapitel vorgestellt. Es gibt
aber auch Anforderungen, die sich durch Default-Argumente nicht lösen lassen.
Zum Beispiel könnte man eine Funktion add() benötigen, die Variablenwerte un-
18
1.3 Nicht-objektorientierte Erweiterungen in C++
terschiedlichen Datentyps addiert. In C waren hierfür immer Funktionen mit verschiedenen Namen notwendig:
void add_i(int i1, int i2);
void add_d(double d1, double d2);
// Addiert zwei Integers
// Addiert zwei Doubles
void add_il(int i1, int i2, long l1);
...
// Addiert zwei Integers und ein long
C++ bietet nun die Möglichkeit, mehrere Funktionen mit gleichem Namen, aber
unterschiedlichen Schnittstellen zu implementieren. Man spricht dabei vom Überladen (Overloading) von Funktionen. Die Entscheidung, welche Funktion bei einem
Aufruf ausgeführt wird, ist abhängig von der Anzahl und vom Datentyp der Argumente, da C++ intern zur Benennung einer Funktion nicht nur deren Namen,
sondern auch die Anzahl und die Typen der Parameter verwendet. Programm 1.1
ist ein Beispiel zum Überladen von Funktionen, indem es die Funktion hoch()
zum Berechnen von xy in drei Varianten anbietet.
Programm 1.1 – overload.cpp:
Überladen einer Funktion zur Berechnung von xy
#include <stdio.h>
#include <math.h>
long
hoch(int y, int x)
{ return (long)pow(x, y);
long
hoch(int y)
{ return (long)pow(10, y); }
double hoch(int y, double x) { return pow(x, y);
}
}
int main(void) {
printf("
3^4 = %ld\n", hoch(4, 3));
printf(" 10^5 = %ld\n", hoch(5));
printf("2.3^4 = %f\n",
hoch(4, 2.3));
return 0;
}
Je nachdem, ob die Funktion hoch() mit zwei int-Argumenten, einem int-Argument oder aber einem int- und einem double-Argument aufgerufen wird, wird
die entsprechende Funktion aufgerufen, so dass sich die folgende Ausgabe für das
Programm 1.1 ergibt:
3^4 = 81
10^5 = 100000
2.3^4 = 27.984100
1.3.5 Inline-Funktionen
Da jeder Funktionsaufruf mit einer Laufzeiterhöhung (aufgrund des erforderlichen
Stackmanagements) verbunden ist, wurden in C bei zeitkritischen Aufgabenstellungen oft Makros anstelle von Funktionen verwendet. Jeder Makroaufruf wurde
dann vom Präprozessor (Precompiler) durch die entsprechenden Anweisungen direkt im Code ersetzt. Die Verwendung von Makros ist jedoch ziemlich aufwendig
und fehleranfällig, da bei einem Makroaufruf nur eine (etwas bessere) Ersetzung
19
1 Einführung in die Objektorientierung und C++
von Text stattfindet, was viele Nebeneffekte auslösen kann, wie beispielsweise die
mehrmalige Auswertung der Argumente.
C++ bietet nun die Möglichkeit, so genannte inline-Funktionen zu definieren,
um die Vorteile von Makros (schnellere Ausführung, da Code der entsprechenden
inline-Funktion an der Aufrufstelle eingefügt wird und somit das Stackmanagement entfällt) mit den Vorteilen von Funktionen (Auswertung der Argumente vor
dem Funktionsaufruf) zu kombinieren. Die Deklaration von inline-Funktionen
entspricht der normaler Funktionen, nur dass das Schlüsselwort inline am Beginn der Funktionsdeklaration angegeben wird. Programm 1.2 zeigt typische Seiteneffekte, die bei Makros, nicht aber bei inline-Funktionen auftreten können.
Programm 1.2 – inline.cpp:
Seiteneffekte von Makros, die bei inline-Funktionen nicht auftreten
#include <stdio.h>
#define quad_makro(zahl)
inline
zahl * zahl
int quad_inline(int zahl) { return zahl*zahl; }
int main(void) {
int z;
z = 3;
printf("quad_makro(++z)
= %d\n", quad_makro(++z) );
// quad_makro(++z) wird zu:
++z * ++z
--> 4*5
z = 3;
printf("quad_inline(++z) = %d\n", quad_inline(++z) );
// quad_inline(++z) wird zu: quad_line(4) --> 4*4
return(0);
}
Programm 1.2 würde folgendes ausgeben:
quad_makro(++z)
= 20
quad_inline(++z) = 16
Da die Anweisungen von inline-Funktionen sowie auch die von Makros direkt
im Code eingefügt werden, sollten beide nur für kleine Aufgaben eingesetzt werden, da dies sonst bei häufigen Aufrufen zu einer „Codeaufblähung“ führt.
1.3.6 Referenzen/Referenz-Operator
Zugriffsmöglichkeiten in C
In C existieren prinzipiell zwei Arten des Zugriffs auf ein im Hauptspeicher (RAM)
liegendes Datum (aus Sicht des C-Programmierers). Zum Verständnis werden beide hier noch einmal kurz vorgestellt:
1. Zugriff auf ein Datum direkt über eine Variable (einen Variablennamen)
20
int
a;
// Variable vom Typ Integer
int
b = 7;
// Variable vom Typ Integer mit Initialisierung
1.3 Nicht-objektorientierte Erweiterungen in C++
a = b;
// Zuweisung des Wertes einer Variablen an eine andere (1)
b = 4;
// Zuweisung eines Wertes an eine Variable
(2)
Dieser Code bewirkt den in Abbildung 1.8 gezeigten Sachverhalt.
a
(1 )
? ? ?
7
b
a
(2 )
7
b
a
7
7
b
4
Abbildung 1.8: Zugriff auf ein Datum über eine Variable
2. Zugriff auf ein Datum über einen Zeiger, der auf das Datum zeigt
int
a;
// Variable vom Typ Integer
int
b = 7;
// Variable vom Typ Integer mit Initialisierung
int* zgr;
// Zeiger auf ein Datum vom Typ Integer
zgr
// Zeiger erhält die Adresse einer Variablen
= &a;
*zgr = b;
(1)
// Wertzuweisung an die vom Zeiger adressierte Variable (2)
Dieser Code bewirkt den in Abbildung 1.9 gezeigten Sachverhalt.
? ? ?
7
? ? ?
a
b
z g r
(1 )
a
b
z g r
? ? ?
7
& a
a
(2 )
b
z g r
7
7
& a
Abbildung 1.9: Zugriff auf ein Datum über einen Zeiger
Zugriff auf ein Datum über eine Referenz in C++
Eine Referenz in C++ kann man sich als zweiten Namen oder als Alias einer Variablen, also eines beliebigen Speicherbereiches, vorstellen. Diesen Alias kann man in
der gleichen Art und Weise verwenden wie die referenzierte Variable.
Der folgende C++-Auszug zeigt eine Möglichkeit der Verwendung einer Referenz:
int
int
a;
b = 7;
int& ref = a;
ref = 4;
// Variable vom Typ Integer
// Variable vom Typ Integer mit Initialisierung
// Referenz auf eine Variable vom Typ Integer
// Wertzuweisung an Variable ’a’ über Variable ’ref’
Dieser Code bewirkt den in Abbildung 1.10 gezeigten Sachverhalt.
D ie s e r S p e ic h e r p la tz k a n n ü b e r z w e i
N a m e n : 'a ' o d e r 'r e f ' a n g e s p r o c h e n w e r d e n
re f / a
b
? ? ?
7
re f / a
b
4
7
Abbildung 1.10: Zugriff auf ein Datum über eine Referenz
21
Kapitel 2
Allgemeines zu Qt
Non quia difficilia sunt non audemus,
sed quia non audemus difficilia sunt.
(Nicht weil es schwer ist, wagen wir es nicht,
sondern weil wir es nicht wagen, ist es schwer.)
– Seneca
Dieses Kapitel klärt zunächst einmal, was Qt überhaupt ist und welche Vorteile Qt
gegenüber anderen GUI-Produkten1 besitzt, bevor der wichtige Qt-Begriff Widget
eingeführt wird. Die nächsten Absätze gehen dann kurz auf die bei Qt mitgelieferte
Dokumentation ein, bevor abschließend auf die Generierung von Qt-Programmen
mit make sowie mit dem eigens von den Qt-Entwicklern angebotenen Tool tmake
zur automatischen Erstellung von Makefiles eingegangen wird.
2.1
Was ist Qt und warum Qt?
Qt ist eine einfache und portable C++-Klassenbibliothek zur
GUI-Programmierung
Qt ist eine von der norwegischen Firma Troll Tech entwickelte C++-Klassenbibliothek, die eine einfache und portable GUI-Programmierung ermöglicht. Manche
Programmierer behaupten sogar, dass Qt die einfachste GUI-Programmierung überhaupt unter den vielen angebotenen GUI-Toolkits erlaubt. Daneben sind mit Qt
entwickelte Programme sowohl unter allen Linux/Unix- wie allen Windows-Systemen lauffähig.
Qt ist ein GUI-Toolkit
GUI-Toolkits sind in der MS-Windows-Welt kaum bekannt, dafür aber um so mehr
in der Unix-Welt. Der Grund hierfür ist, dass die Windows-GUI-Schnittstelle API
schon von sich aus eine high-level-Schnittstelle ist, die z. B. Buttons, Laufbalken
oder Funktionen zum Ändern von Farben und Fonts anbietet.
1 GUI
steht für „Graphical User Interface“.
115
2 Allgemeines zu Qt
Anders verhält sich dagegen die unter Unix angebotene Schnittstelle des X Window System, die zwar sehr flexibel ist, aber nur low-level-Funktionen anbietet, wie
z. B. zum Zeichnen primitiver Graphiken (Linien, Rechtecke usw.) oder zum Setzen der Hinter- und Vordergrundfarbe. Diese X-Window-Schnittstelle bietet keine high-level-Funktionen zum Erzeugen von Buttons, Laufbalken, Dialogboxen
usw. Dies ist der Grund, warum einige Toolkits entwickelt wurden, um die GUIProgrammierung unter Unix zu vereinfachen. Der bekannteste Toolkit dürfte Motif
sein, was nicht nur ein Toolkit, sondern auch eine Spezifikation für ein bestimmtes
„look-and-feel“ ist. Allerdings ist die Verwendung von Motif sehr schwierig und
äußerst mühsam, was sich daran erkennen lässt, dass Motif-Programme wesentlich
länger sind als Qt-Programme, die das gleiche leisten. Nichtsdestotrotz ist Motif ein
Standard. Qt ist nun ein GUI-Toolkit, der dieses look-and-feel von Motif mit einer
wesentlich einfacheren GUI-Programmierschnittstelle zur Verfügung stellt.
Nun noch einmal zurück zum Windows-API, das Funktionen anbietet, um GUIElemente (wie Buttons, Menüs usw.) zu erzeugen, Farben zu ändern usw. Diese
API-Schnittstelle ist zwar wesentlich einfacher als das direkte Programmieren des
X Window System, aber sie ist immer noch nicht benutzerfreundlich genug.
Daneben existiert noch die Microsoft Foundation Class (MFC), welche zwar highlevel-Funktionen anbietet, aber doch sehr komplex in ihrer Verwendung ist. Bei
der Benutzung von MFC muss der Benutzer immer noch sehr viel Zeit aufwenden,
um eine Bedienoberfläche zu erzeugen, statt sich auf den eigentlichen Kern seiner
Aufgabe zu konzentrieren.
Qt ist nun ein so genanntes application framework, das alle die eben erwähnten Nachteile vermeidet. Unter einem Framework versteht man ein komplettes Programmiersystem, das dem Programmierer die low-level-Arbeiten abnimmt. Dazu stellt
es ihm eine Bibliothek von Klassen zur Verfügung, so dass er sich Objekte definieren kann, die genau ein user-interface-Element repäsentieren (wie z. B. einen Button
oder ein Menü), und er so über die vom Programmiersystem bereitgestellten Konstrukte alle Anwenderinteraktionen mit diesen Elementen verwalten kann.
Vorteile von Qt
Für die Verwendung von Qt bei der Entwicklung neuer Software sprechen die folgenden Vorzüge:
❏ Qt ist für Unix-Systeme (wie Linux, FreeBSD oder Solaris) frei, wenn man freie
Software für diese Systeme schreibt.
❏ Qt ist portabel und einfach. Programme, die mit Qt geschrieben werden, sind so-
wohl unter Linux/Unix als auch unter Windows lauffähig, was z. B. für MFC
nicht gilt, denn mit MFC entwickelte Programme sind nur unter WindowsSystemen lauffähig. Zudem stufen viele Programmierer, die sowohl mit MFC
als auch mit Qt gearbeitet haben, Qt als einfacher ein.
❏ Qt ist schnell. Programme, die mit Qt geschrieben sind, laufen sehr schnell ab.
116
2.2 Der Begriff „Widget“
2.2
Der Begriff „Widget“
Qt arbeitet mit so genannten Widgets. Dieser Begriff wird unter Unix für Windows
(Fenster) verwendet: „Widget“ ist eine Wortschöpfung aus den beiden Begriffen
„Window“ und „Gadget“ (entspricht Controls unter Windows-Betriebssystemen).
Nahezu alles, was man auf einer in Qt geschriebenen Oberfläche sieht, ist ein Widget: Buttons, Laufbalken, Dialogboxen usw. Widgets können ihrerseits wieder Subwidgets enthalten, wie z. B. Buttons oder Texteingabefelder in einer Dialogbox.
In Qt ist ein Widget ein Objekt einer Klasse, die von der Klasse QWidget abgeleitet
ist. Qt enthält viele vordefinierte Widgets, allerdings kann der Qt-Programmierer
auch seine eigenen Widgets definieren.
2.3
Die Qt-Online-Dokumentation im HTML-Format
Qt bietet eine hervorragende Online-Dokumentation im HTML-Format an. Deswegen ist es in dieser Qt-Einführung auch nicht notwendig, eine Qt-Referenz anzugeben, da mit jeder Qt-Distribution eine vollständige Online-Qt-Referenz mitgeliefert
wird. Um diese Online-Dokumentation zu lesen, muss ein Web-Browser wie z. B.
Netscape Navigator verwendet werden. Andere Browser, wie z. B. arena oder lynx
unter Linux sind auch möglich, da die Qt-Online-Dokumentation weder spezielle
HTML-Konstrukte verwendet noch Java oder JavaScript voraussetzt.
Abbildung 2.1: Startseite der Qt-Referenz-Dokumentation
117
2 Allgemeines zu Qt
Im Browser ist dann zuerst die Datei index.html im Verzeichnis doc der entsprechenden Qt-Installation zu öffnen (unter Linux/Unix-Systemen meist:
/usr/lib/qt/doc/html bzw. /usr/lib/qt2/doc/html)
um die Titelseite der Qt-Dokumentation einzublenden (siehe auch Abbildung 2.1).
Um einen Eindruck zu bekommen, wie der Qt-Klassenbaum organisiert ist, sollte
man zunächst den Punkt Annotated Class List anklicken. Man bekommt dann eine
Liste aller Qt-Klassen, die public sind, mit einer einzeiligen Kurzbeschreibung
angezeigt. Später, nachdem man mit Qt etwas mehr vertraut ist, kann man dann
meist direkt von der Startseite zum Punkt Alphabetical Class List wechseln. Die dann
eingeblendete Liste enthält keine Kurzbeschreibung und zeigt mehr Klassen auf
einer Seite.
Um einen ersten Eindruck über die Beschreibung der einzelnen Klassen zu bekommen, kann man z. B. auf den Link QButton klicken. QButton ist die Klasse, die für
die Erzeugung von Buttons und deren Interaktionen mit dem Programm zuständig
ist (siehe auch Abbildung 2.2).
In Abbildung 2.2 sieht man als erste Zeile eine Kurzbeschreibung der jeweiligen
Klasse. In der zweiten Zeile ist dann der Name der Headerdatei angegeben, in der
diese Klasse definiert ist. Es folgt der Name der Basisklasse, von der diese Klasse
abgeleitet ist, bevor in der nächsten Zeile eine Liste der Klassen angegeben ist, die
wiederum von dieser Klasse (hier QButton) abgeleitet sind, was in Abbildung 2.2
die Klassen QCheckBox, QPushButton, QRadioButton und QToolButton sind.
Der Link List of all member functions ist wichtig für den Fall, dass man einen Überblick über alle Memberfunktionen haben möchte, also nicht nur die Memberfunk-
Abbildung 2.2: Die Referenz-Dokumentation für QButton
118
2.4 Die Qt-Dokumentation als Postscript-Datei
tionen, die in der Klasse selbst definiert sind, sondern auch über die, welche diese
Klasse von ihren übergeordneten Klassen erbt.
Anschließend folgt eine Liste aller Public Members, die direkt in dieser Klasse definiert sind, sowie etwaige Listen von Public Slots, Signals oder Protected Members, die
diese Klasse anbietet.
Nach diesen Listen wird eine detaillierte Beschreibung der entsprechenden Klasse
gegeben, die oft ganze Beispiele enthält, wie diese Klasse zu verwenden ist.
2.4
Die Qt-Dokumentation als Postscript-Datei
Die Qt-Herstellerfirma Troll Tech bietet eine sehr gute Qt-Dokumentation als Postscript-Dateien auf ihrem Webserver http://www.trolltech.com zum Herunterladen an.
2.5
Kompilieren von Qt-Programmen
Um Qt-Programme zu kompilieren, existieren zwei Möglichkeiten:
❏ die direkte Eingabe der Kommandozeile, was mit der Zeit sehr mühsam ist,
oder aber
❏ das Arbeiten mit Makefiles.
Direkte Eingabe der Kommandozeile
Hier wird nur exemplarisch die Programmgenerierung für den Compiler Visual C++
(auf Windows-Betriebssystemen) und den Compiler GNU C++ (auf Unix-Systemen)
vorgestellt. Daneben existieren weitere Möglichkeiten der Programmgenerierung,
wie z. B. für den Compiler Borland C++ (auf Windows-Betriebssystemen) und für
nahezu alle in der Unix-Welt bekannten Compiler. Diese werden hier nicht alle
vorgestellt. Jedoch entspricht die Programmgenerierung auch auf für diese Compiler im Wesentlichen der hier vorgestellten Vorgehensweise.
Arbeitet man mit dem Microsoft Visual-C++-Compiler unter einem Windows-Betriebssystem, muss man die beiden folgenden Kommandozeilen eingeben, wenn
Qt im Directory c:nqt installiert wurde.
cl -c -nologo -W3 -O1 -DNO_DEBUG -I"C:\qt\include" -Fo prog.obj prog.cpp
link /NOLOGO /SUBSYSTEM:windows /OUT:myprog.exe myprog.obj C:\qt\lib\qt.lib
user32.lib gdi32.lib comdlg32.lib imm32.lib ole32.lib uuid.lib wsock32.lib
Auf Unix-Systemen sollte zunächst die Environmentvariable QTDIR gesetzt werden (z. B. export QTDIR=/usr/lib/qt oder export QTDIR=/usr/lib/qt2).
Um dann ein Qt-Programm zu kompilieren, muss die folgende Kommandozeile
eingegeben werden:
c++ -I$QTDIR/include -L$QTDIR/lib -lqt -o prog prog.cpp
119
2 Allgemeines zu Qt
Abhängig vom jeweiligen Unix-System kann diese Kommandozeile auch etwas anders aussehen. Die obige Kommandozeile gilt jedenfalls für alle Systeme, die den
GNU C++-Compiler verwenden.
Arbeiten mit Makefiles
In diesem Fall ist das von Firma Troll Tech zur Verfügung gestellte Tool tmake sehr
hilfreich. Für tmake muss man nur eine entsprechende .pro-Datei erstellen, wie
z. B. die folgende Datei myprog.pro:
TEMPLATE = app
CONFIG
= qt warn_on release
HEADERS
= cannon.h gamebrd.h lcdrange.h
SOURCES
= cannon.cpp gamebrd.cpp lcdrange.cpp main.cpp
unix:LIBS= -lm
TARGET
= myprog
Um sich nun das entsprechende Makefile2 erstellen zu lassen, muss man dann
nur noch folgendes aufrufen
❏ unter Windows-Betriebssystemen:
tmake myprog.pro -o Makefile -win32
❏ unter Linux/Unix-Betriebssystemen:
tmake myprog.pro -o Makefile -unix
Das von tmake erzeugte Makefile hat z. B. für Windows-Betriebssysteme, unter
denen mit Visual-C++ gearbeitet wird, folgendes Aussehen (aus Platzgründen etwas komprimiert):
####### Compiler, tools and options
CC
= cl
CXX
= cl
CFLAGS
= -nologo -W3 -O1 -DNO_DEBUG
CXXFLAGS= -nologo -W3 -O1 -DNO_DEBUG
INCPATH = -I"$(QTDIR)\include"
LINK
= link
LFLAGS
= /NOLOGO /SUBSYSTEM:windows
LIBS
= $(QTDIR)\lib\qt.lib user32.lib gdi32.lib comdlg32.lib imm32.lib
ole32.lib uuid.lib wsock32.lib
MOC
= moc
ZIP
= zip -r -9
####### Files
HEADERS = cannon.h
gamebrd.h
lcdrange.h
SOURCES = cannon.cpp gamebrd.cpp lcdrange.cpp main.cpp
OBJECTS = cannon.obj gamebrd.obj lcdrange.obj main.obj
SRCMOC
= moc_cannon.cpp moc_gamebrd.cpp moc_lcdrange.cpp
OBJMOC
= moc_cannon.obj moc_gamebrd.obj moc_lcdrange.obj
DIST
=
TARGET
= myprog.exe
2 Das Tool make und die Syntax von Makefiles ist im Buch „Linux-Unix Profitools“ von Helmut
Herold (Addison-Wesley) detailliert beschrieben.
120
2.5 Kompilieren von Qt-Programmen
####### Implicit rules
.SUFFIXES: .cpp .cxx .cc .c
.cpp.obj:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ $<
.cxx.obj:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ $<
.cc.obj:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ $<
.c.obj:
$(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ $<
####### Build rules
all: $(TARGET)
$(TARGET): $(OBJECTS) $(OBJMOC)
$(LINK) $(LFLAGS) /OUT:$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
moc: $(SRCMOC)
tmake: Makefile
Makefile: myprog.pro
tmake myprog.pro -o Makefile
dist:
$(ZIP) myprog.zip myprog.pro $(SOURCES) $(HEADERS) $(DIST)
clean:
-del cannon.obj
-del gamebrd.obj
-del lcdrange.obj
-del main.obj
-del moc_cannon.cpp
-del moc_gamebrd.cpp
-del moc_lcdrange.cpp
-del moc_cannon.obj
-del moc_gamebrd.obj
-del moc_lcdrange.obj
-del $(TARGET)
####### Compile
cannon.obj:
cannon.cpp cannon.h
gamebrd.obj:
gamebrd.cpp gamebrd.h lcdrange.h cannon.h
lcdrange.obj: lcdrange.cpp lcdrange.h
main.obj:
main.cpp gamebrd.h lcdrange.h cannon.h
moc_cannon.obj:
moc_cannon.cpp cannon.h
moc_gamebrd.obj:
moc_gamebrd.cpp gamebrd.h lcdrange.h cannon.h
moc_lcdrange.obj: moc_lcdrange.cpp lcdrange.h
moc_cannon.cpp: cannon.h
$(MOC) cannon.h -o moc_cannon.cpp
moc_gamebrd.cpp: gamebrd.h
$(MOC) gamebrd.h -o moc_gamebrd.cpp
moc_lcdrange.cpp: lcdrange.h
$(MOC) lcdrange.h -o moc_lcdrange.cpp
121
2 Allgemeines zu Qt
Nachdem dieses Makefile automatisch erstellt wurde, muss man unter WindowsSystemen nur noch
nmake
aufrufen, um ein ausführbares Programm zu generieren. Die von tmake unter
Linux/Unix-Systemen erzeugten Makefiles sehen weitgehend ähnlich aus, nur dass
sie z. B. andere Pfadnamen für die Headerdateien und Bibliotheken sowie eventuell auch andere Makronamen im Makefile enthalten. Unter Linux/Unix muss man
dann
make
aufrufen, um ein ausführbares Programm zu generieren.
122
Kapitel 6
Vordefinierte Dialogfenster
Genau betrachtet, ist alles Gespräch nur Selbstgespräch.
– C. Morgenstern
Ein Dialogfenster ist ein Widget, das für eine spezielle Kommunikation mit dem
Benutzer ausgelegt ist, wie z. B. Auswahl einer bestimmten Farbe oder einer Datei. Qt bietet für solche typischen Kommunikationen mit dem Benutzer eine ganze
Reihe von vordefinierten Dialogfenstern an, die schon mit entsprechenden Auswahlmöglichkeiten und/oder Buttons versehen sind und so dem Qt-Programmierer eine Menge Arbeit abnehmen.
Die wichtigsten von Qt vordefinierten Dialogfenster sind:
QDialog: Basisklasse für vordefinierte Dialogfenster
QColorDialog: zur Auswahl einer Farbe
QFileDialog: zur Auswahl einer Datei (z. B. zum Öffnen oder Speichern)
QFontDialog: zur Auswahl eines Font (Zeichensatzes)
QMessageBox: zur Anzeige von kurzen Informationen, die der Benutzer durch
Drücken der dazu angebotenen Buttons bestätigen muss.
QTabDialog: zur Stapelung von Widgets im Karteikartenformat, von denen über
eine Karteikartenreiterleiste (Tableiste) immer eines in den Vordergrund gebracht
werden kann.
QWizard: zum Blättern in einer vorgegebenen Menge von Widgets. Dabei kann
immer nur eine Seite vor- bzw. zurückgeblättert werden. Es wird dabei immer
nur die aktuelle Seite angezeigt, während die anderen Seiten nicht sichtbar sind.
QPrinter: zum Drucken mit möglichen Druckereinstellungen
QInputDialog: für einfache Eingaben, wie z. B. Zahlen, Text oder Auswahl aus
einer vorgegebenen Liste
QProgressDialog: zur Anzeige in Form eines Prozentbalkens, wie weit eine bestimmte Aktion schon fortgeschritten ist
417
6 Vordefinierte Dialogfenster
6.1
Die Basisklasse QDialog
Zunächst soll hier der Begriff modal geklärt werden, denn jedes Dialogfenster kann
entweder modal oder nicht-modal sein:
❏ Ein nicht-modaler Dialog ist ein normales Window, das, während es eingeblendet ist, ein gleichzeitiges Arbeiten in anderen Windows dieses Programms zulässt.
❏ Ein modaler Dialog dagegen ist ein Window, das kein gleichzeitiges Arbeiten
mit anderen Windows zulässt, während es eingeblendet ist. Erst nach der
Beendigung eines modalen Dialogfensters ist es dem Benutzer wieder erlaubt,
Aktivitäten in anderen Windows dieses Programms durchzuführen.
Konstruktor und Methoden der Basisklasse QDialog
Die Klasse QDialog bietet einen Konstruktor an:
QDialog(QWidget *parent=0, const char *name=0,
bool modal=false, WFlags f=0)
Der Parameter modal legt dabei fest, ob es sich um einen modalen oder nichtmodalen Dialog handelt.
Die Klasse QDialog bietet den folgenden enum-Datentyp, der für das Resultat eines modalen Dialogs vorgesehen ist:
enum DialogCode { Rejected, Accepted };
Wichtige Methoden, die die Klasse QDialog anbietet, sind:
int exec(): startet den entsprechenden Dialog und liefert die Antwort des Benutzers auf diesen Dialog als Rückgabewert. Der Aufruf von exec() ist identisch mit einem Aufruf show(), gefolgt von einem result()-Aufruf. Während
diese Funktion für modale Dialoge sehr nützlich ist, macht sie keinen Sinn für
nicht-modale Dialoge. Der Rückgabewert von exec() zeigt an, wie der Dialog beendet wurde: QDialog::Accepted (Button OK wurde gedrückt) bzw.
QDialog::Rejected (Button Cancel wurde gedrückt).
int result() const: liefert das Resultat des Dialogs als Rückgabewert. Wie
exec() macht auch diese Methode nur Sinn bei modalen Dialogen.
setResult(int) protected: setzt das Resultat des Dialogs auf Wert r.
Die Klasse QDialog bietet unter anderem die folgenden Slotroutinen an:
accept() virtual protected slot: schließt den Dialog und setzt das Resultat auf den Wert Accepted; entspricht dem Aufruf done(Accepted).
reject() virtual protected slot: schließt den Dialog und setzt das Resultat auf den Wert Rejected; entspricht dem Aufruf done(Rejected).
done(int r) virtual protected slot: schließt den Dialog und setzt das
Resultat auf den Wert r; entspricht dem Aufruf hide(), gefolgt von setResult(r).
Beispiel: Einblenden eines modalen oder nicht-modalen Dialogfensters
Programm 6.1 ermöglicht es dem Benutzer, sich ein modales oder ein nicht-modales
Dialogfenster anzeigen zu lassen. Die Voreinstellung ist das Einblenden eines nicht-
418
6.1 Die Basisklasse QDialog
Abbildung 6.1: Modales Dialogfenster von Programm 6.1 mit Anzeige der Benutzerwahl
(rechts)
modalen Dialogfensters. Wird beim Aufruf dieses Programms die Option -m angegeben, wird ein modales Dialogfenster eingeblendet, wie es im linken Teil der Abbildung 6.1 gezeigt ist. Nachdem der Benutzer einen der beiden Buttons angeklickt
hat, wie z. B. den OK-Button, wird ihm in einem Nachrichtenfenster (Messagebox)
seine Auswahl nochmals bestätigt (siehe auch rechter Teil der Abbildung 6.1).
Programm 6.1 – dialog.cpp:
Demoprogramm zur Klasse QDialog
#include <qwidget.h>
#include <qapplication.h>
#include <qdialog.h>
#include <qpushbutton.h>
#include <qmessagebox.h>
//.............................................................. MeinDialog
class MeinDialog : public QDialog {
public:
MeinDialog::MeinDialog( QWidget *parent, QString name, bool modal=true )
: QDialog( parent, name, modal ) {
QPushButton *ok = new QPushButton( "OK", this );
ok->setGeometry( 10,10, 100,30 );
connect( ok, SIGNAL(clicked()), SLOT(accept()) );
if ( modal ) {
QPushButton *cancel = new QPushButton( "Cancel", this );
cancel->setGeometry( 10,60, 100,30 );
connect( cancel, SIGNAL(clicked()), SLOT(reject()) );
}
}
};
//.................................................................... main
int main( int argc, char *argv[] ) {
419
6 Vordefinierte Dialogfenster
QApplication a( argc, argv );
QWidget *w = new QWidget;
w->setGeometry( 10, 10, 300, 300 );
w->setPalette( QPalette( Qt::blue, Qt::blue ) );
w->show();
if ( argc > 1 && !strcmp( argv[1], "-m" ) ) {
MeinDialog
*modal = new MeinDialog( w, 0, true );
modal->setCaption( "Modaler Dialog" );
modal->setPalette( QPalette( Qt::red,Qt::red ) );
int r = modal->exec();
QString s;
s.sprintf("Du hast ‘%s’ gedrueckt!",
r == QDialog::Accepted ? "OK" : "Cancel" );
QMessageBox::information( 0, "Nur zu deiner Info", s );
} else {
MeinDialog
*nichtModal = new MeinDialog( w, 0, false );
nichtModal->setCaption( "Nicht-Modaler Dialog" );
nichtModal->setPalette( QPalette( Qt::red, Qt::red ) );
nichtModal->show();
}
a.setMainWidget( w );
return a.exec();
}
Übung: Dialog-Widget mit Checkboxen und mehreren Pushbuttons
Erstellen Sie ein Programm dialog2.cpp, das ein Dialog-Widget mit Checkboxen
einblendet, die der Benutzer ein- und ausschalten kann, sowie mit mehreren Buttons, die ihn seine Auswahl z. B. bestätigen oder ignorieren lassen. Unter Zuhilfenahme dieses Widget soll dann der Benutzer in den Checkboxen Länder auswählen
können, zu denen er Flaggen angezeigt haben möchte (siehe auch Abbildung 6.2).
Klickt der Benutzer auf den Ok-Button, werden ihm die Flaggen zu den Ländern
angezeigt, die er in den Checkboxen ausgewählt hat. Bei einem Klick auf den Button Europäische sollen ihm in jedem Fall alle europäischen Flaggen und eventuell
Abbildung 6.2: Eigenes Dialog-Widget zur Auswahl von Länderflaggen
420
6.2 Klasse QColorDialog zur Auswahl einer Farbe
zusätzlich angeklickte Länderflaggen angezeigt werden. Klickt der Benutzer auf
den Button Alle, sollen ihm unabhängig von seiner Auswahl in den Checkboxen
alle Länderflaggen angezeigt werden.
Ein Klick auf den Cancel-Button beendet unabhängig von der vorgenommenen Auswahl das Programm ohne jegliche Anzeige von Länderflaggen.
6.2
Klasse QColorDialog zur Auswahl einer
Farbe
Die Klasse QColorDialog bietet keine Konstruktoren an, sondern nur statische
Funktionen, wie z. B. die Methode getColor(), die ein Dialogfenster zur Auswahl
einer Farbe einblendet:
QColor QColorDialog::getColor(QColor initial,
QWidget *parent=0,
const char *name=0)
Diese Funktion blendet ein modales Dialogfenster ein, das dem Benutzer eine Farbe
auswählen lässt (siehe auch Abbildung 6.3). In diesem Dialogfenster ist die Farbe,
die mit dem Parameter initial übergeben wird, voreingestellt. Die vom Benutzer
ausgewählte Farbe liefert diese Funktion dann als Rückgabewert, nachdem dieser
den Ok-Button gedrückt hat und das Dialogfenster wieder ausgeblendet wurde.
Hat der Benutzer den Cancel-Button gedrückt, liefert diese Funktion einen ungültigen Farbenwert, der sich mit der von der Klasse QColor angebotenen Methode
isValid() erkennen lässt.
Neben der statischen Methode getColor() bietet die Klasse QColorDialog noch
einige weitere statische Methoden an, wie z. B.:
QRgb QColorDialog::getRgba(QRgb initial, bool *ok=0, QWidget
*parent=0, const char *name=0) static: blendet wie getColor()
ein modales Dialogfenster ein, das dem Benutzer eine Farbe auswählen lässt.
Anders als bei getColor() hat der Benutzer hier noch die Möglichkeit, einen
Alpha-Kanal (unterhalb des Blue-Eingabefelds) festzulegen. Ist für ok kein
Nullzeiger angegeben, so wird *ok auf true gesetzt, wenn der Benutzer den
Ok-Button gedrückt hat, bzw. auf false , wenn er den Cancel-Button gedrückt
hat.
int QColorDialog::customCount() static: liefert die Anzahl der als Custom colors im QColorDialog-Widgets festgelegten Farben.
QRgb QColorDialog::customColor(int i) static: liefert die i-te festgelegte Farbe aus den Custom colors des QColorDialog-Widget.
QColorDialog::setCustomColor(int i, QRgb c) static: setzt die i-te
Farbe von Custom colors im QColorDialog-Widget auf den QRgb-Wert c.
Programm 6.2 ist ein Demonstrationsprogramm zur Klasse QColorDialog. Dieses Programm bietet im Hauptfenster eine Widget-Fläche mit einem Button an, mit
dem man sich ein QColorDialog-Fenster (siehe auch Abbildung 6.3) einblenden
lassen kann, um eine neue Farbe auszuwählen. Nach abgeschlossener Auswahl
und Bestätigung dieser Wahl mit dem Ok-Button wird die neu gewählte Farbe in
421
6 Vordefinierte Dialogfenster
Abbildung 6.3: Ein QColorDialog-Fenster
der Widget-Fläche des Hauptfensters als Hintergrundfarbe angezeigt (siehe auch
Abbildung 6.4). Die zu Beginn voreingestellte Hintergundfarbe ist Weiß.
Programm 6.2 – colordialog.cpp:
Demoprogramm zur Auswahl einer Farbe mit QColorDialog
#include <qwidget.h>
#include <qapplication.h>
#include <qpushbutton.h>
#include <qcolordialog.h>
//............................................................... MeinFarbe
Abbildung 6.4: Hauptfenster des Programms 6.2
422
6.3 Klasse QFileDialog zur Auswahl einer Datei
class MeinFarbe : public QWidget {
Q_OBJECT
public:
MeinFarbe::MeinFarbe() : QWidget( 0, 0) {
setBackgroundColor( aktFarbe = Qt::white );
farbeButton = new QPushButton( "Neue Farbe", this );
connect( farbeButton, SIGNAL( clicked() ), SLOT( neueFarbe() ) );
setGeometry( 0, 0, 400, 400 );
}
private slots:
void
neueFarbe() {
QColor neuFarbe;
neuFarbe = QColorDialog::getColor( aktFarbe, 0 );
if ( neuFarbe.isValid() ) {
setBackgroundColor( aktFarbe = neuFarbe );
repaint();
}
}
private:
QPushButton *farbeButton;
QColor
aktFarbe;
};
#include "colordialog.moc"
//.................................................................... main
int main( int argc, char *argv[] ) {
QApplication a( argc, argv );
MeinFarbe *w = new MeinFarbe;
w->show();
a.setMainWidget( w );
return a.exec();
}
Übung: Anzeige eines Textes in einer über QColorDialog gewählten Farbe
Erstellen Sie ein Programm colordialog2.cpp, das ähnlich zu Programm 6.2
einen Button Neue Farbe und zusätzlich ein Label mit einem Text einblendet. Bei jedem Klick auf den Button Neue Farbe soll ein QColorDialog-Fenster eingeblendet
werden, in dem der Benutzer eine neue Farbe wählen kann. Bestätigt er hier seine gewählte Farbe mit den Ok-Button, soll ihm der Text im Label mit dieser Farbe
angezeigt werden.
6.3
Klasse QFileDialog zur Auswahl einer Datei
Die Klasse QFileDialog bietet ein vordefiniertes Dialogfenster zur Auswahl eines
Dateinamens an.
423
6 Vordefinierte Dialogfenster
Konstruktoren und Methoden der Klasse QFileDialog
Die Klasse QFileDialog bietet zwei Konstruktoren an:
QFileDialog(QWidget *parent=0, const char *name=0, bool modal=false): erzeugt ein QFileDialog-Widget. Ob es sich dabei um ein
modales oder nicht-modales Dialogfenster handelt, kann mit dem Parameter
modal festgelegt werden.
QFileDialog(const QString& dirName, const QString& filter=QString::null, QWidget *parent=0, const char *name=0,
bool modal=false): erzeugt ein QFileDialog-Widget. Der Parameter
dirName legt den Namen des Directory fest, aus dem die entsprechenden
Dateien (für eine Auswahl) anzuzeigen sind. Der Parameter filter spezifiziert
den Filter, der für die Anzeige von Dateinamen zu benutzen ist. Als Filter sind
dabei reguläre Ausdrücke erlaubt, wie sie in einem späteren Kapitel beschrieben
sind. Dabei ist es auch erlaubt, Texte anzugeben, die zur Information für den
Benutzer dienen. In diesem Fall muss der entsprechende reguläre Ausdruck am
Ende des entsprechenden Textes in runden Klammern angegeben werden; so
liefern z. B. die beiden folgenden Angaben die gleiche Anzeige von Dateinamen
in dem QFileDialog-Widget, nur dass die erste Angabe etwas informativer
ist: "Alle C-Header- und Quelldateien (*.[ch])" bzw. "*.[ch]".
Es ist auch möglich, mehrere Filter anzugeben, indem man diese durch neue
Zeilen oder zwei Semikola trennt, wie z. B. "C++ Dateien (*.cpp *.cc
*.C *.cxx *.c++);;Headerdateien (*.h *.hxx *.h++)". Ob es sich
dabei um ein modales oder nicht-modales Dialogfenster handelt, kann mit dem
Parameter modal festgelegt werden.
Wichtige Methoden, die die Klasse QFileDialog anbietet, sind:
QString getOpenFileName(const QString& startWith=QString::null, const QString& filter=QString::null,
QWidget *parent=0, const char *name=0) static: Diese statische
Funktion, die man verwenden kann, um ein QFileDialog-Fenster einzublenden, ohne dass man ein eigenes QFileDialog-Objekt anlegt, findet sehr häufige
Anwendung. Sie öffnet ein modales QFileDialog-Fenster und liefert den vom
Benutzer ausgewählten Dateinamen zurück.
Wenn startWith ein Directoryname ist, startet der Dialog in diesem Directory. Ist startWith der Pfadname einer existierenden Datei, startet der Dialog
in dem zugehörigen Directory, wobei der entsprechende Dateiname schon als
ausgewählt angezeigt wird. Ist startWith ein Leerstring startet der Dialog im
Working Directory und beim erneuten Aufrufen immer in dem Directory, in dem
das letzte QFileDialog-Fenster beendet wurde.
Sollen nur bestimmte Dateinamen im Dialogfenster angezeigt werden, so muss
für den Parameter filter ein entsprechender regulärer Ausdruck angegeben
werden. Falls für filter der Wert QString::null eingestellt wird, werden
alle Dateinamen des entsprechenden Directory im Dialogfenster angezeigt. Falls
der Benutzer das Dialogfenster mit dem Drücken des Cancel-Button beendet, liefert diese Funktion den null-String als Rückgabewert. Nachfolgend ist ein Beispiel für den Aufruf dieser Methode gezeigt:
424
6.3 Klasse QFileDialog zur Auswahl einer Datei
//... im Working-Directory alle C++-Dateien mit der Endung .cpp anzeigen
QString d = QFileDialog::getOpenFileName( QString::null, "*.cpp", this );
if ( !d.isEmpty() ) {
//... Benutzer hat eine existierende Datei ausgewählt
} else {
//... Benutzer hat das Dialogfenster mit dem Cancel-Button beendet
}
QStringList getOpenFileNames(const QString& filter=QString::null, const QString& dir=QString::null, QWidget *parent=0, const char *name=0) static: Diese statische Funktion entspricht weitgehend der Funktion getOpenFileName(), nur dass sie den
Benutzer mehrere Dateien auswählen lässt und diese dann als Rückgabewert
liefert, wie z. B.:
QStringList s( QFileDialog::getOpenFileNames() );
//... Bearbeiten der Dateien in s
QString getSaveFileName(const QString& startWith=QString::null, const QString& filter=QString::null,
QWidget *parent=0, const char *name=0) static: Diese statische
Funktion entspricht weitgehend der Funktion getOpenFileName(), nur mit
dem einzigen Unterschied, dass hier der Benutzer auch eine nicht existierende
Datei auswählen kann, was ja beim Sichern von Dateien unter einem neuen
Namen auch unbedingt notwendig ist.
QString getExistingDirectory(const QString&
dir=QString::null, QWidget *parent=0, const char *name=0)
static: Diese statische Funktion blendet ein Dialogfenster ein, in dem der
Benutzer ein existierendes Directory auswählen kann, das sie als Rückgabewert liefert. Welches Directory dabei beim Start des Dialogfensters der
Ausgangspunkt sein soll, kann mit dem Parameter dir festgelegt werden. Falls
dir=null gilt, wird als Ausgangspunkt das Directory genommen, in dem das
letzte QFileDialog-Fenster beendet wurde.
setDir(const QString& pathstr) slot: legt einen Directorypfad für ein
QFileDialog-Fenster fest.
QString dirPath() const: liefert den aktuellen Directorypfad eines QFileDialog-Fensters zurück.
setSelection(const QString& filename): markiert in einem QFileDialog-Fenster den Dateinamen filename als ausgewählt. Falls es sich bei filename um einen absoluten Pfadnamen handelt, so wird automatisch auch setDir() aufgerufen.
QString selectedFile() const: liefert zu der in einem QFileDialogFenster ausgewählten Datei den absoluten Pfadnamen. Falls kein Dateiname
ausgewählt wurde, wird der null-String zurückgegeben.
setFilter(const QString& newFilter) slot: legt für ein QFileDialog-Fenster einen neuen Filter fest, der als regulärer Ausdruck anzugeben ist,
wie dies bereits beim zweiten Konstruktor zuvor beschrieben wurde.
425
6 Vordefinierte Dialogfenster
setMode(Mode newMode): legt für ein QFileDialog-Fenster einen neuen Modus fest. Für den Parameter newMode kann dabei eine der folgenden Konstanten
angegeben werden:
❏ Directory: Auswahl von Directories ist erlaubt
❏ ExistingFile: Auswahl von existierenden Dateien ist erlaubt
❏ AnyFile: Angabe von beliebigen Dateinamen (ob existierend oder nicht)
ist erlaubt
❏ DirectoryOnly: Nur Auswahl von Directories erlaubt; andere Dateien
werden nicht angezeigt.
❏ ExistingFiles: wie ExistingFile, nur dass auch Auswahl mehrerer
Dateien erlaubt ist
addWidgets(QLabel *l, QWidget *w, QPushButton *b) protected:
fügt bis zu drei Widgets unten in dem QFileDialog-Widget hinzu. l ist dabei
ein (optionales) Label, welches unterhalb der Spalte angeordnet wird, in der
sich die Texte File name und File type befinden. w ist ein (optionales) Widget, das
unterhalb der Kombobox für den File type platziert wird. b ist ein (optionaler)
Button, der unterhalb des Cancel-Button angesiedelt wird. Soll eines dieser
optionalen Widgets nicht angezeigt werden, muss für den entsprechenden
Parameter nur der Wert 0 angegeben werden.
rereadDir(): zwingt ein QFileDialog-Fenster den entsprechenden Directoryinhalt erneut zu lesen. Dies kann notwendig sein, wenn sich der Directoryinhalt
ändert, nachdem das QFileDialog-Fenster für dieses Directory schon eingeblendet war.
Die Klasse QFileDialog bietet die folgenden Signale an:
fileHighlighted(const QString&) signal: wird gesendet, wenn der Benutzer einen Dateinamen markiert.
fileSelected(const QString&) signal: wird gesendet, wenn der Benutzer einen Dateinamen auswählt.
dirEntered(const QString&) signal: wird gesendet, wenn der Benutzer
ein neues Directory ausgewählt hat.
Abbildung 6.5: QFileDialog-Fenster zur Auswahl einer Datei im Programm 6.3
426
6.3 Klasse QFileDialog zur Auswahl einer Datei
Abbildung 6.6: Laden eines Bildes (links) bzw. eines Textes (rechts) im Programm 6.3
Die Klasse QFileDialog bietet noch weitere Methoden an, mit denen man z. B.
unter Zuhilfenahme der Klasse QFilePreview eine Vorschau zu Dateien einblenden kann oder unter Verwendung der Klasse QFileIconProvider die Dateinamen abhängig von ihrem Inhalt mit entsprechenden Icons versehen kann. Auf eine
tiefergehende Behandlung dieser Methoden wird hier verzichtet. Der interessierte
Leser kann diese in der Qt-Online-Dokumentation nachschlagen.
Beispiel: Editor, der Betrachtung/Konvertierung von Bildern ermöglicht
Programm 6.3 ist ein Demonstrationsprogramm zur Klasse QFileDialog. Über
ein QFileDialog-Fenster (siehe Abbildung 6.5) kann dabei der Benutzer sich eine
Datei auswählen. Handelt es sich dabei um eine Bilddatei, deren Format Qt interpretieren kann, so wird ihm das entsprechende Bild angezeigt, wie dies z. B. im
linken Teil von Abbildung 6.6 gezeigt ist. Kann Qt das Format der entsprechenden
Datei nicht als ein ihm bekanntes Bildformat interpretieren, liest das Programm 6.3
diese Datei als Textdatei in ein QMultiLineEdit-Widget ein, welches das Editieren dieses Textes ermöglicht, wie dies z.B im rechten Teil von Abbildung 6.6
gezeigt ist. Das Speichern einer Datei ist dabei auch möglich, wie dies in Abbildung 6.7 gezeigt ist. Handelt es sich bei der entsprechenden Datei um ein Bild, so
konvertiert das Programm 6.3 das Bild bei der Speicherung abhängig von der Dateiendung automatisch in das entsprechende Bildformat (.png, .gif, .bmp, .xbm,
.xpm, .pnm).
Programm 6.3 – filedialog.cpp:
Texteditor, der auch Betrachtung und Konvertierung von Bildern ermöglicht
#include <qapplication.h>
#include <qlabel.h>
#include <qmultilinedit.h>
#include <qfiledialog.h>
#include <qmenubar.h>
427
6 Vordefinierte Dialogfenster
Abbildung 6.7: QFileDialog-Fenster zur Auswahl eines Dateinamens zur Speicherung
im Programm 6.3
#include <qpopupmenu.h>
#include <qtextstream.h>
#include <qmessagebox.h>
enum { SchliessenID=255, SpeichernID, SpeichernUnterID };
//==========================================================================
//
V i e w e r
-
K l a s s e
//==========================================================================
class Viewer : public QWidget {
Q_OBJECT
// notwendig, da Slots enthalten sind
public:
Viewer();
private slots:
void schliessenSlot() { //............................ schliessenSlot
if ( view != NULL ) {
delete view;
view = NULL;
dateiName = ""; setzeTitel( "keine" );
dateiMenu->setItemEnabled( SchliessenID, false );
dateiMenu->setItemEnabled( SpeichernID, false );
dateiMenu->setItemEnabled( SpeichernUnterID, false );
}
}
void beendenSlot() {
//............................... beendenSlot
schliessenSlot(); qApp->quit();
void oeffnenSlot() {
}
//............................... oeffnenSlot
QString name = QFileDialog::getOpenFileName( ".", "*", this );
if ( !name.isEmpty() ) {
dateiName = name;
schliessenSlot();
leseDatei();
dateiMenu->setItemEnabled( SchliessenID, true );
dateiMenu->setItemEnabled( SpeichernID, true );
dateiMenu->setItemEnabled( SpeichernUnterID, true );
428
6.3 Klasse QFileDialog zur Auswahl einer Datei
}
}
void speichernSlot() {
//........................... speichernSlot
if (view != NULL) speichereDatei( false );
void speichernUnterSlot() {
}
//................. speichernUnterSlot
if (view != NULL) speichereDatei( true );
}
protected:
virtual void resizeEvent( QResizeEvent* ) { //........... resizeEvent
if (view != NULL) {
view->setGeometry( 0, menuBalken->height(),
width(), height() - menuBalken->height() );
if ( istBild )
bildView->setGeometry( 0,0, width(),height()-menuBalken->height() );
else
textView->setGeometry( 0,0, width(),height()-menuBalken->height() );
repaint();
}
}
private:
void leseDatei() { //...................................... leseDatei
QFile
datei;
if ( !dateiName.isEmpty() ) {
datei.setName( dateiName );
setzeTitel( dateiName );
view = new QWidget( this );
if ( bild.load( dateiName ) ) {
bildView = new QScrollView( view );
bildView->viewport()->setBackgroundColor( Qt::white );
QLabel *l = new QLabel( bildView->viewport() );
l->setPixmap( bild );
l->setFrameStyle( QFrame::Box | QFrame::Sunken );
l->setLineWidth( 4 );
l->resize( l->sizeHint() );
istBild = true;
bildView->addChild( l );
bildView->setGeometry( 0,0, width(),height()-menuBalken->height() );
} else if ( datei.open(IO_ReadOnly) ) {
QTextStream text( &datei );
// verwende einen text stream
QString s;
textView = new QMultiLineEdit( view );
while ( !text.eof() ) {
s = text.readLine();
textView->insertLine( s );
}
datei.close();
istBild = false;
textView->setGeometry( 0,0,width(),height()-menuBalken->height() );
}
view->setGeometry( 0, menuBalken->height(),
width(), height() - menuBalken->height() );
429
6 Vordefinierte Dialogfenster
view->show();
}
}
void speichereDatei( bool neuerName ) { //............ speichereDatei
if ( dateiName.isEmpty() || neuerName == true )
dateiName = QFileDialog::getSaveFileName( ".", "*", this );
if ( !dateiName.isEmpty() ) {
setzeTitel( dateiName );
if ( istBild ) {
QString extension = dateiName.mid(
dateiName.findRev(’.’)+1 ).upper();
if ( !bild.save( dateiName, extension ) )
QMessageBox::information( this, "Fehler",
extension+"-Format wird nicht unterstützt");
} else {
QFile
datei;
datei.setName( dateiName );
if ( datei.open(IO_WriteOnly) ) {
QString
text = textView->text();
datei.writeBlock( text, strlen(text) );
datei.close();
}
}
}
}
void
setzeTitel( QString dateiname ) { //................ setzeTitel
QString s = "Viewer - Datei: ";
s += dateiname;
setCaption( s );
}
//............................................... private-Variablen
QMenuBar
*menuBalken;
QPopupMenu
*dateiMenu;
QString
dateiName;
QWidget
*view;
QMultiLineEdit *textView;
QScrollView
*bildView;
QPixmap
bild;
bool
istBild;
};
#include "filedialog.moc"
//==========================================================================
//
V i e w e r
-
K o n s t r u k t o r
//==========================================================================
Viewer::Viewer() {
view = NULL;
dateiName
= "";
setzeTitel( "keine");
dateiMenu = new QPopupMenu; //... erzeugt ein Datei-Menue
dateiMenu->insertItem( "Oe&ffnen...", this, SLOT( oeffnenSlot() ), CTRL+Key_O );
430
6.4 Klasse QFontDialog zur Auswahl eines Font
dateiMenu->insertItem( "S&chliessen", this, SLOT( schliessenSlot() ),
CTRL + Key_W, SchliessenID );
dateiMenu->setItemEnabled( SchliessenID, false );
dateiMenu->insertSeparator();
dateiMenu->insertItem( "&Speichern", this, SLOT( speichernSlot() ),
CTRL + Key_S, SpeichernID );
dateiMenu->setItemEnabled( SpeichernID, false );
dateiMenu->insertItem( "Speichern &unter...", this, SLOT( speichernUnterSlot() ),
CTRL + Key_U, SpeichernUnterID );
dateiMenu->setItemEnabled( SpeichernUnterID, false );
dateiMenu->insertSeparator();
dateiMenu->insertItem( "&Beenden", this, SLOT( beendenSlot() ), CTRL+Key_Q );
menuBalken = new QMenuBar( this ); //... erzeugt einen Menue-Balken
menuBalken->insertItem( "&Datei", dateiMenu );
}
//==========================================================================
//
m a i n
//==========================================================================
int main( int argc, char* argv[] ) {
QApplication myapp( argc, argv );
Viewer* mywidget = new Viewer();
mywidget->setGeometry( 10, 10, 600, 600 );
myapp.setMainWidget( mywidget );
mywidget->show();
return myapp.exec();
}
Übung: Anzeige ausgewählter Dateinamen in einem Label
Erstellen Sie ein Programm filedialog2.cpp, das eine Erweiterung zum Übungsprogramm colordialog2.cpp auf Seite 423 ist, indem es nicht nur einen
Farbe-Button, sondern auch einen Dateinamen-Button zeigt. Klickt der Benutzer auf
diesen zweiten Button, soll ihm ein QFileDialog-Widget eingeblendet werden,
in dem er auch mehrere Dateinamen gleichzeitig auswählen kann (mit QFileDialog::getOpenFileNames()), indem er bei dem Anklicken der Dateinamen die
Strg -Taste drückt. Nachdem der Benutzer seine Auswahl mit Ok bestätigt hat,
sollen ihm die ausgewählten Dateinamen in der aktuellen Farbe angezeigt werden;
siehe auch Abbildung 6.8.
6.4
Klasse QFontDialog zur Auswahl eines Font
Die Klasse QFontDialog bietet ein vordefiniertes Dialogfenster zur Auswahl eines
Font an.
431
6 Vordefinierte Dialogfenster
Abbildung 6.8: Anzeige von ausgewählten Dateinamen in einem Label
Wichtige Methoden der Klasse QFontDialog
Die Klasse QFontDialog bietet keine public-Konstruktoren an, sondern nur eine statische Funktion getFont(), die ein Dialogfenster zur Auswahl eines Font
einblendet und in zwei Varianten angeboten wird:
QFont getFont(bool *ok, QWidget *parent=0,const char *name=0) static: Diese Funktion blendet ein modales Dialogfenster ein, das
den Benutzer einen Font auswählen lässt (siehe auch Abbildung 6.10). Den
vom Benutzer ausgewählten Font liefert diese Funktion dann als Rückgabewert,
nachdem dieser den Ok-Button gedrückt hat und das Dialogfenster wieder
ausgeblendet wurde. Ob der Benutzer den Ok-Button gedrückt hat, lässt sich
am Wert des Parameters ok erkennen. Ist *ok=true, hat er den Ok-Button gedrückt; bei *ok=false hat er das QFontDialog-Fenster mit dem Cancel-Button
beendet oder eben anders geschlossen. Bei *ok=false liefert diese Funktion
den voreingestellten Font zurück.
Beispiel:
bool ok;
QFont f = QFontDialog::getFont( &ok, this );
if ( ok ) {
//... Benutzer hat einen neuen Font ausgewählt
} else {
//... Benutzer hat Dialogfenster mit Cancel-Button oder anders beendet
}
QFont getFont(bool *ok, const QFont& initial, QWidget *parent=0, const char *name=0) static: Diese Variante entspricht weitgehend der vorhergehenden Aufrufvariante, nur dass im QFontDialog-Fenster
der über den Parameter initial übergebene Font voreingestellt wird.
432
6.4 Klasse QFontDialog zur Auswahl eines Font
Abbildung 6.9: Angezeigtes Hauptfenster beim Start von Programm 6.4
Beispiel:
bool ok;
QFont f = QFontDialog::getFont( &ok, QFont( "Times", 12 ), this );
if ( ok ) {
//... Benutzer hat einen neuen Font ausgewählt
} else {
//... Benutzer hat Dialogfenster mit Cancel-Button oder anders beendet
}
Abbildung 6.10: QFontDialog-Fenster zur Auswahl eines Font im Programm 6.4
433
6 Vordefinierte Dialogfenster
Abbildung 6.11: Hauptfenster im Programm 6.4, nachdem Benutzer neuen Font gewählt
hat
Beispiel: Demonstrationsprogramm zur Klasse QFontDialog
Programm 6.4 zeigt in seinem Hauptfenster (siehe Abbildung 6.9) in einem Label
den gerade gesetzten Font in Form eines Beispieltextes (Text) an. Die dazugehörigen Font-Daten werden in einem darunter angeordneten Label angezeigt. Als letztes bietet dieses Programm noch einen Button an, mit dem man sich ein QFontDialog-Fenster einblenden lassen kann, um einen neuen Font auszuwählen. Drückt
der Benutzer auf diesen Button, wird ihm ein solches neues QFontDialog-Fenster
eingeblendet, in dem er nun seine entsprechenden Font-Einstellungen vornehmen
kann, wie dies z. B. in Abbildung 6.10 gezeigt ist. Drückt der Benutzer in diesem
QFileDialog-Fenster den Ok-Button, werden ihm im Hauptfenster der Beispieltext Text in seinem gewählten Font sowie die zugehörigen Font-Daten angezeigt
(siehe auch Abbildung 6.11).
Programm 6.4 – fontdialog.cpp:
Demoprogramm zur Klasse QFontDialog
#include <qwidget.h>
#include <qapplication.h>
#include <qvbox.h>
#include <qpushbutton.h>
#include <qlabel.h>
#include <qfont.h>
#include <qfontdialog.h>
//................................................................ MeinFont
class MeinFont : public QVBox {
Q_OBJECT
public:
434
6.4 Klasse QFontDialog zur Auswahl eines Font
MeinFont::MeinFont() : QVBox( 0, 0) {
//.................. Vertikaler Layoutmanger
QVBox *v = new QVBox( this );
v->setSpacing( 20 );
v->setMargin( 20 );
v->setBackgroundColor( Qt::blue.light( 180 ) );
//.... Label zur Anzeige des aktuellen Fonts
fontAnzeige = new QLabel( "Text", v );
fontAnzeige->setBackgroundColor( Qt::white );
fontAnzeige->setAlignment( AlignCenter );
aktFont = fontAnzeige->font();
//.... Label zur Anzeige der aktuellen Fontdaten
fontDaten = new QLabel( "", v );
fontDaten->setText( fontToString() );
fontDaten->setAlignment( AlignCenter );
//.... Buttom zum Einblenden QFontDialog-Fensters
fontButton = new QPushButton( "Neuer Font", v );
fontButton->setPalette( QPalette( Qt::red, Qt::red ) );
connect( fontButton, SIGNAL( clicked() ), SLOT( neuerFont() ) );
setGeometry( 0, 0, 400, 400 );
}
private slots:
void
neuerFont() {
QFont
neuFont;
bool
ok;
neuFont = QFontDialog::getFont( &ok, aktFont );
if ( ok ) {
fontAnzeige->setFont( aktFont = neuFont );
fontAnzeige->repaint();
fontDaten->setText( fontToString() );
fontDaten->repaint();
}
}
private:
QFont
aktFont;
QLabel
*fontAnzeige;
QLabel
*fontDaten;
QPushButton *fontButton;
//... liefert die Font-Daten als String zurueck.
//... Dazu ruft diese Funktion die von der Klasse QFont angebotenen
//... Methoden family(), weight(), italic() pointSize(),
//... underline() und strikeOut() auf.
QString fontToString() {
QString s, weight;
switch ( aktFont.weight() ) {
case QFont::Light:
weight = "Light";
break;
case QFont::Normal:
weight = "Normal";
break;
case QFont::DemiBold: weight = "DemiBold"; break;
case QFont::Bold:
weight = "Bold";
break;
case QFont::Black:
weight = "Black";
break;
435
6 Vordefinierte Dialogfenster
}
s.sprintf("%s-%s-%s-%d\n\n%sUnderline-%sStrikeout\n",
(const char *)aktFont.family(),
(const char *)weight,
(const char *)aktFont.italic() ? "Italic" : "",
aktFont.pointSize(),
(const char *)aktFont.underline() ? "" : "No",
(const char *)aktFont.strikeOut() ? "" : "No" );
return s;
}
};
#include "fontdialog.moc"
//.................................................................... main
int main( int argc, char *argv[] ) {
QApplication a( argc, argv );
MeinFont *w = new MeinFont;
w->setGeometry( 20, 20, 400, 400 );
w->show();
a.setMainWidget( w );
return a.exec();
}
Übung: Erweiterung des Übungsprogramms aus Kapitel 6.4 um Fonts
Erstellen Sie ein Programm fontdialog2.cpp, das eine Erweiterung zum Übungsprogramm filedialog2.cpp auf Seite 431 ist, indem es nicht nur einen Farbe-Button und einen Dateinamen-Button, sondern auch einen Font-Button zeigt. Klickt der Benutzer auf diesen dritten Button, soll ihm ein QFontDialog-Widget eingeblendet werden, in dem er sich einen entsprechenden Font für die Anzeige der
Dateinamen im Label auswählen kann.
6.5
Klasse QMessageBox für Mitteilungen
Die Klasse QMessageBox ermöglicht es, den Benutzer über Situationen, Ereignisse
oder Bedingungen zu informieren, die eingetreten sind oder aber eintreten könnten. QMessageBox-Dialogfenster sind fast immer modal.
Typen, Konstruktoren und Methoden der Klasse QMessageBox
Die Klasse QMessageBox bietet zwei eigene enum-Datentypen an:
enum Icon { NoIcon=0, Information=1, Warning=2, Critical=3 }:
Diese Konstanten legen das Icon (Bildchen) fest, das im QMessageBox-Fenster
anzuzeigen ist:
NoIcon: kein Icon
Information: (Buchstabe ,i‘ in einer Sprechblase) wird verwendet, wenn man
dem Benutzer lediglich eine Information zukommen lassen möchte.
436
6.5 Klasse QMessageBox für Mitteilungen
Warning: (Ausrufezeichen in einem Warnschild) wird verwendet, wenn man
den Benutzer warnen möchte.
Critical: (weißes ,x‘ in einem schwarzen Kreis) wird verwendet, um den Benutzer auf eine kritische Situation hinzuweisen, die eingetreten ist oder eintreten könnte.
enum { Ok=1, Cancel=2, Yes=3, No=4, Abort=5, Retry=6, Ignore=7, ButtonMask=0x07, Default=0x100, Escape=0x200, FlagMask=0x300 }: Diese Konstanten identifizieren Texte bzw. Einstellungen für
Buttons, die in einem QMessageBox-Fenster angezeigt werden.
Die Klasse QMessageBox bietet zwei Konstruktoren an:
QMessageBox(QWidget *parent=0, const char *name=0): erzeugt ein
QMessageBox-Widget, das keinerlei Text, aber einen Button mit der Beschriftung Ok enthält.
QMessageBox(const QString& caption, const QString& text,
Icon icon, int button0, int button1, int button2, QWidget *parent=0, const char *name=0, bool modal=true, WFlags
f=WStyle_DialogBorder): Bei dieser Konstruktor-Variante wird ein QMessageBox-Widget erzeugt, dessen Titel durch den Parameter caption und
dessen Informationstext durch den Parameter text festgelegt ist. Für den
Parameter icon ist eine der folgenden Konstanten anzugeben:
❏ QMessageBox::NoIcon
❏ QMessageBox::Information
❏ QMessageBox::Warning
❏ QMessageBox::Critical
Für die drei Parameter button0, button1 und button2 ist eine der folgenden
Konstanten anzugeben:
❏ QMessageBox::Ok
❏ QMessageBox::Cancel
❏ QMessageBox::Yes
❏ QMessageBox::No
❏ QMessageBox::Abort
❏ QMessageBox::Retry
❏ QMessageBox::Ignore
Einer dieser drei Buttons kann mit bitweisem OR mit der Konstante QMessageBox::Default verknüpft werden, was ihn zum Default-Button macht. Der
Default-Button ist der Button, auf den automatisch der Tastaturfokus eingestellt
wird und der so direkt durch Drücken der - -Taste ausgewählt (gedrückt) werden kann.
Einer dieser drei Buttons kann mit bitweisem OR mit der Konstante QMessage
ESC -Taste verbindet. Dies
Box::Escape verknüpft werden, was ihn mit der bedeutet, dass beim Drücken der ESC -Taste (auf der Tastatur) immer dieser Button aktiviert wird, so als ob man auf diesen Button mit der Maus geklickt hätte.
Der Parameter modal schließlich legt fest, ob ein modales oder ein nicht-modales
QMessageBox-Widget zu erzeugen ist.
437
6 Vordefinierte Dialogfenster
Nachfolgend ist ein kleiner Codeausschnitt für ein Nachrichtenfenster gezeigt,
das beim Beenden eines Editors eingeblendet wird, wenn der Benutzer den Editor verlassen möchte, ohne dass er zuvor seine Datei gesichert hat.
QMessageBox mb( "Datei noch nicht gesichert",
"Was soll geschehen?",
QMessageBox::Information,
QMessageBox::Yes | QMessageBox::Default,
QMessageBox::No,
QMessageBox::Cancel | QMessageBox::Escape );
mb.setButtonText( QMessageBox::Yes,
"Sichern" );
mb.setButtonText( QMessageBox::No,
"Nicht sichern" );
mb.setButtonText( QMessageBox::Cancel, "Abbrechen" );
switch ( mb.exec() ) {
case QMessageBox::Yes:
//... Datei speichern und Editor verlassen
break;
case QMessageBox::No:
//... Datei nicht speichern und Editor verlassen
break;
case QMessageBox::Cancel:
//... Datei nicht speichern und Editor nicht vwerlasse
break;
}
Man kann jedoch auch direkt ein QMessageBox-Fenster einblenden, ohne explizit
ein Objekt dazu mittels eines Konstruktors anzulegen. Dazu bietet Qt die folgenden
statischen Methoden an:
int information(QWidget *parent, const QString& caption, const QString& text, const QString& button0Text=QString::null, const QString& button1Text=QString::null, const QString& button2Text=QString::null, int defaultButtonNumber=0, int
escapeButtonNumber=-1) static: blendet ein QMessageBox-Fenster
des Typs Information ein, dessen Titel durch den Parameter caption und
dessen Informationstext durch den Parameter text festgelegt wird. Die nächsten drei Parameter buttonXText spezifizieren den Text für die einzelnen
Buttons (bis zu drei). Ist für button0Text kein Argument angegeben, wird
hierfür ein Ok-Button angezeigt, während ein Weglassen der beiden letzten
optionalen Buttons dazu führt, dass diese Buttons überhaupt nicht angezeigt
werden. Der Parameter defaultButtonNumber spezifiziert dann den DefaultButton (0, 1 oder 2) und der Parameter escapeButtonNumber spezifiziert den
Escape-Button (0, 1 oder 2). Diese Funktion liefert die Nummer des Button, den
der Benutzer gedrückt hat, als Rückgabewert (0, 1 oder 2).
int information(QWidget *parent, const QString& caption,
const QString& text, int button0, int button1=0, int button2=0) static: blendet ein QMessageBox-Fenster des Typs Information
ein, dessen Titel durch den Parameter caption und dessen Informationstext
438
6.5 Klasse QMessageBox für Mitteilungen
durch den Parameter text festgelegt wird. Dieses QMessageBox-Fenster
enthält bis zu drei Buttons, deren Text der Benutzer durch die entsprechenden
Kennungen (Ok, Cancel, Yes, ...) festlegen kann. Die Angabe von 0 für einen
der Parameter button0, button1 oder button2 legt fest, dass dieser Button
nicht anzuzeigen ist. Diese Funktion liefert die Nummer des Button, den der
Benutzer gedrückt hat, als Rückgabewert (0, 1 oder 2).
int warning(QWidget *parent, const QString& caption, const
QString& text, const QString& button0Text=QString::null,
const QString& button1Text=QString::null, const QString&
button2Text=QString::null, int defaultButtonNumber=0, int
escapeButtonNumber=-1) static: entspricht der entsprechenden information()-Methode (siehe oben), nur dass das eingeblendete QMessageBoxFenster vom Typ Warning ist.
int warning(QWidget *parent, const QString& caption, const
QString& text, int button0, int button1=0, int button2=0)
static: entspricht der entsprechenden information()-Methode (siehe
oben), nur dass das eingeblendete QMessageBox-Fenster vom Typ Warning ist.
int critical(QWidget *parent, const QString& caption, const
QString& text, const QString& button0Text=QString::null,
const QString& button1Text=QString::null, const QString&
button2Text=QString::null, int defaultButtonNumber=0, int
escapeButtonNumber=-1) static: entspricht der entsprechenden information()-Methode (siehe oben), nur dass das eingeblendete QMessageBoxFenster vom Typ Critical ist.
int critical(QWidget *parent, const QString& caption, const
QString& text, int button0, int button1=0, int button2=0)
static: entspricht der entsprechenden information()-Methode (siehe
oben), nur dass das eingeblendete QMessageBox-Fenster vom Typ Critical
ist.
about(QWidget *parent, const QString& caption, const
QString& text) static: Diese statische Methode blendet ein QMessageBox-Widget mit dem Titel caption und dem Informationstext text
ein, in dem sich lediglich ein Ok-Button befindet (siehe auch linken Teil in
Abbildung 3.9 auf Seite 167).
aboutQt(QWidget *parent, const QString& caption=QString::null) static: Diese statische Methode blendet ein QMessageBox-Widget mit dem Titel caption und einigen Informationen zu Qt
(wie z. B. die Versionsnummer) als Informationstext ein; in diesem QMessageBox-Widget befindet sich lediglich ein Ok-Button (siehe auch rechten Teil in
Abbildung 3.9 auf Seite 167).
Nachfolgend werden nun noch einige Methoden vorgestellt, mit denen man nachträglich ein zuvor mit einem Konstruktor erzeugtes QMessageBox-Objekt entsprechend konfigurieren kann:
setText(const QString& text): legt den anzuzeigenden Informationstext
für ein QMessageBox-Objekt fest.
439
6 Vordefinierte Dialogfenster
Abbildung 6.12: Hauptfenster im Programm 6.5 zur Konfiguration einer QMessageBox
setIcon(Icon icon): legt das anzuzeigende Icon (NoIcon, Information,
Warning, Critical) für ein QMessageBox-Objekt fest.
setIconPixmap(const QPixmap& pixmap): ermöglicht es, ein benutzerdefiniertes Icon (pixmap) für ein QMessageBox-Objekt festzulegen.
setButtonText(int button, const QString& text): legt in einem QMessageBox-Objekt für den entsprechenden button, der die hier angegebene
Kennung (Ok, Cancel, Yes, No, Abort, Retry, Ignore) besitzt, den anzuzeigenden text fest.
Beispiel: Demonstrationsprogramm zur Klasse QMessageBox
Programm 6.5 bietet über eine Menüleiste alle möglichen Konfigurationen für ein
QMessageBox-Widget an (siehe Abbildung 6.12). Nachdem der Benutzer eine
neue Konfiguration über einen Eintrag in dieser Menüleiste vorgenommen hat,
wird ihm das entsprechende QMessageBox-Widget eingeblendet (siehe auch Abbildung 6.13). Nachdem der Benutzer dieses QMessageBox-Widget mit einem
Klick auf einen der drei Buttons beendet hat, wird ihm in einem neuen QMessageBox-Fenster vom Typ Information seine Auswahl bestätigt (siehe auch Abbildung 6.14).
Abbildung 6.13: Anzeige des konfigurierten QMessageBox-Fensters im Programm 6.5
440
6.5 Klasse QMessageBox für Mitteilungen
Abbildung 6.14: Anzeige der Benutzerwahl aus Abbildung 6.13 im Programm 6.5
Programm 6.5 – messagebox.cpp:
Demoprogramm zur Klasse QMessageBox
#include <qapplication.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qlineedit.h>
#include <qmessagebox.h>
#include <stdio.h>
const int
texteId
= 0x1000;
const int
IconId
= 0x2000;
const int
ButtonId
= 0x3000;
const int
DefaultId = 0x4000;
const int
EscId
= 0x5000;
enum { CaptionId=texteId, InfotextId
};
enum { NoIconId=IconId, InformationId, WarningId, CriticalId
};
enum { OkId=ButtonId, CancelId, YesId, NoId, AbortId, RetryId, IgnoreId };
//......................................................... Klasse MyWidget
class MyWidget : public QWidget {
Q_OBJECT
// notwendig, da Slots enthalten sind
public:
MyWidget() {
//______________ MyWidget (Konstruktor)
//.................. Initialisierungen
caption
= "";
escButton = 2;
infoText = "Informationstext";
icon
defaultButton = 0;
= QMessageBox::NoIcon;
button[0] = QMessageBox::Yes | QMessageBox::Default;
button[1] = QMessageBox::No;
button[2] = QMessageBox::Cancel | QMessageBox::Escape;
//...............Texte-Menu
texteMenu = new QPopupMenu;
texteMenu->insertItem( "Caption", CaptionId );
texteMenu->insertItem( "Infotext", InfotextId );
QObject::connect( texteMenu, SIGNAL( activated( int ) ),
this,
SLOT( texteSlot( int ) ) );
lc = new QLineEdit( caption, this );
li = new QLineEdit( infoText, this );
lc->setGeometry(10, 30, 100, 30 );
li->setGeometry(10, 30, 100, 30 );
lc->hide();
li->hide();
QObject::connect( lc,
SIGNAL( returnPressed() ),
441
6 Vordefinierte Dialogfenster
this, SLOT( neuerCaptionSlot() ) );
QObject::connect( li,
SIGNAL( returnPressed() ),
this, SLOT( neuerInfoTextSlot() ) );
//................ Icon-Menu
iconMenu = new QPopupMenu;
iconMenu->insertItem( "NoIcon",
NoIconId );
iconMenu->insertItem( "Information", InformationId );
iconMenu->insertItem( "Warning",
WarningId );
iconMenu->insertItem( "Critcal",
CriticalId );
iconMenu->setItemChecked( NoIconId, true );
QObject::connect( iconMenu, SIGNAL( activated( int ) ),
this, SLOT( iconSlot( int ) ) );
//............ button-Menues
for (int i=0; i<3; i++) {
buttonMenu[i] = new QPopupMenu;
buttonMenu[i]->insertItem( "Ok",
OkId );
buttonMenu[i]->insertItem( "Cancel", CancelId );
buttonMenu[i]->insertItem( "Yes",
YesId );
buttonMenu[i]->insertItem( "No",
NoId );
buttonMenu[i]->insertItem( "Abort",
AbortId );
buttonMenu[i]->insertItem( "Retry",
RetryId );
buttonMenu[i]->insertItem( "Ignore", IgnoreId );
}
buttonMenu[0]->setItemChecked( YesId, true );
buttonMenu[1]->setItemChecked( NoId, true );
buttonMenu[2]->setItemChecked( CancelId, true );
QObject::connect( buttonMenu[0], SIGNAL( activated( int ) ),
this, SLOT( button0Slot( int ) ) );
QObject::connect( buttonMenu[1], SIGNAL( activated( int ) ),
this, SLOT( button1Slot( int ) ) );
QObject::connect( buttonMenu[2], SIGNAL( activated( int ) ),
this, SLOT( button2Slot( int ) ) );
//............. Default-Menu
defaultMenu = new QPopupMenu;
defaultMenu->insertItem( "Button0", DefaultId
);
defaultMenu->insertItem( "Button1", DefaultId+1 );
defaultMenu->insertItem( "Button2", DefaultId+2 );
defaultMenu->setItemChecked( DefaultId+defaultButton, true );
QObject::connect( defaultMenu, SIGNAL( activated( int ) ),
this,
SLOT( defaultSlot( int ) ) );
//................. Esc-Menu
escMenu = new QPopupMenu;
escMenu->insertItem( "Button0", EscId
);
escMenu->insertItem( "Button1", EscId+1 );
escMenu->insertItem( "Button2", EscId+2 );
escMenu->setItemChecked( EscId+escButton, true );
QObject::connect( escMenu, SIGNAL( activated( int ) ),
this, SLOT( escSlot( int ) ) );
//............... Menu-Balken
menuBalken = new QMenuBar( this );
442
6.5 Klasse QMessageBox für Mitteilungen
menuBalken->insertItem( "Texte",
texteMenu );
menuBalken->insertItem( "Icon",
iconMenu );
menuBalken->insertItem( "Button0", buttonMenu[0] );
menuBalken->insertItem( "Button1", buttonMenu[1] );
menuBalken->insertItem( "Button2", buttonMenu[2] );
menuBalken->insertItem( "Default", defaultMenu );
menuBalken->insertItem( "Esc",
escMenu );
}
private slots:
void texteSlot( int s ) {
//_______________________________ Slots
switch ( s ) {
case CaptionId : lc->show(); break;
case InfotextId: li->show(); break;
}
}
void neuerCaptionSlot() {
caption = lc->text();
lc->hide();
neueMessageBox();
}
void neuerInfoTextSlot() {
infoText = li->text();
li->hide();
neueMessageBox();
}
void iconSlot( int s ) {
switch ( s ) {
case NoIconId
: icon = QMessageBox::NoIcon;
break;
case InformationId: icon = QMessageBox::Information; break;
case WarningId
: icon = QMessageBox::Warning;
break;
case CriticalId
: icon = QMessageBox::Critical;
break;
}
for (int i=NoIconId; i <= CriticalId; i++)
iconMenu->setItemChecked( i, s == i );
neueMessageBox();
}
void button0Slot( int s ) { buttonConfigure( s, 0); }
void button1Slot( int s ) { buttonConfigure( s, 1); }
void button2Slot( int s ) { buttonConfigure( s, 2); }
void defaultSlot( int s ) {
button[defaultButton] &= ~QMessageBox::Default;
button[defaultButton=s-DefaultId] |= QMessageBox::Default;
for (int i=DefaultId; i <= DefaultId+2; i++)
defaultMenu->setItemChecked( i, s == i );
neueMessageBox();
}
void escSlot( int s ) {
button[escButton] &= ~QMessageBox::Escape;
button[escButton=s-EscId] |= QMessageBox::Escape;
for (int i=EscId; i <= EscId+2; i++)
443
6 Vordefinierte Dialogfenster
escMenu->setItemChecked( i, s == i );
neueMessageBox();
}
private:
void buttonConfigure( int s, int n ) {
switch ( s ) {
case OkId
: button[n] = QMessageBox::Ok;
break;
case CancelId: button[n] = QMessageBox::Cancel; break;
case YesId
: button[n] = QMessageBox::Yes;
break;
case NoId
: button[n] = QMessageBox::No;
break;
case AbortId : button[n] = QMessageBox::Abort;
break;
case RetryId : button[n] = QMessageBox::Retry;
break;
case IgnoreId: button[n] = QMessageBox::Ignore; break;
}
if ( n == defaultButton ) button[n] |= QMessageBox::Default;
if ( n == escButton ) button[n] |= QMessageBox::Escape;
for (int i=OkId; i <= IgnoreId; i++)
buttonMenu[n]->setItemChecked( i, s == i );
neueMessageBox();
}
void neueMessageBox() {
QString neuInfoText;
neuInfoText.sprintf("%s\n\n\n"
"
(Button%d = Default-Button)\n"
"
(Button%d = Escape-Button)\n",
(const char *)infoText, defaultButton, escButton);
QMessageBox *mb = new QMessageBox( caption, neuInfoText, icon,
button[0], button[1], button[2], this );
mb->setPalette( QPalette( Qt::red, Qt::red ) );
int ret = mb->exec();
delete mb;
QString info = "Du hast den Button\"";
switch ( ret ) {
case QMessageBox::Ok:
info+= "Ok";
break;
case QMessageBox::Cancel: info+= "Cancel"; break;
case QMessageBox::Yes:
info+= "Yes";
break;
case QMessageBox::No:
info+= "No";
break;
case QMessageBox::Abort:
info+= "Abort";
break;
case QMessageBox::Retry:
info+= "Retry";
break;
case QMessageBox::Ignore: info+= "Ignore"; break;
}
info += "\" gewaehlt";
QMessageBox::information( this, "Nur zur Info", info );
}
QMenuBar
*menuBalken;
QPopupMenu *texteMenu, *iconMenu, *buttonMenu[3], *defaultMenu, *escMenu;
QString
caption, infoText;
int
button[3], defaultButton, escButton;
QLineEdit
*lc, *li;
QMessageBox::Icon
444
icon;
6.5 Klasse QMessageBox für Mitteilungen
Abbildung 6.15: Auswahl eines Landes über Messageboxen
};
#include "messagebox.moc"
//.................................................................... main
int main( int argc, char* argv[] ) {
QApplication myapp( argc, argv );
MyWidget*mywidget = new MyWidget();
mywidget->setGeometry( 10, 10, 400, 300 );
mywidget->setPalette( QPalette( Qt::lightGray, Qt::blue ) );
myapp.setMainWidget( mywidget );
mywidget->show();
return myapp.exec();
}
Übung: Auswahl eines Landes und Anzeige dessen Flagge
Erstellen Sie ein Programm messagebox2.cpp, das zunächst eine Messagebox
einblendet, wie sie links in Abbildung 6.15 gezeigt ist. Klickt der Benutzer den
Button Weiter, wird ihm eine nächste Wahlmöglichkeit gezeigt (siehe Mitte in Abbildung 6.15). Klickt der Benutzer auch hier wieder auf den Button Weiter, wird
ihm eine dritte und letzte Wahlmöglichkeit gezeigt (siehe rechts in Abbildung 6.15).
Sollte er sich auch hier nicht für ein Land entscheiden können und klickt nun auf
den Button None, wird ihm schließlich noch eine letzte Messagebox (siehe Abbildung 6.16) eingeblendet, in der er lediglich mit einem Klick auf den Ok-Button das
Programm beenden kann. Sollte der Benutzer sich aber in einer der drei Messageboxen aus Abbildung 6.15 für ein Land entschieden haben, wird ihm die Flagge
dieses Landes als Icon in einer Messagebox eingeblendet, wie dies beispielhaft für
die Länder „Britain“ und „USA“ in Abbildung 6.17 gezeigt ist.
Abbildung 6.16: Messagebox, wenn Benutzer kein Land auswählte
445
6 Vordefinierte Dialogfenster
Abbildung 6.17: Anzeige der Flagge des gewählten Landes in einer Messagebox
6.6
Klasse QTabDialog zur Stapelung von
Widgets im Karteikartenformat
Die Klasse QTabDialog ermöglicht die Stapelung von Widgets im Karteikartenformat, von denen über eine Karteikartenreiterleiste (Tableiste) immer eines in den
Vordergrund gebracht werden kann.
Konstruktor und Methoden der Klasse QTabDialog
Die Klasse QTabDialog bietet einen Konstruktor an:
QTabDialog(QWidget *parent=0, const char *name=0,
bool modal=false, Wflags f=0)
erzeugt ein QTabDialog-Widget mit einem Ok-Button.
Die übliche Vorgehensweise beim Programmieren einer QTabDialog-Anwendung
ist die folgende:
1. Erzeugen eines QTabDialog-Widget (mit dem obigen Konstruktor).
2. Erzeugen von QWidget-Objekten für jede Seite, die in diesem QTabDialogWidget untergebracht werden sollen.
3. Einfügen der entsprechenden Subwidgets (eventuell unter Verwendung von
Layout-Managern) in die einzelnen QWidget-Objekte der entsprechenden Seiten.
4. Aufrufen der Methode addTab(), um die einzelnen Seiten (QWidget-Objekte) in dem QTabDialog-Widget einzuordnen.
5. Einrichten der einzelnen Buttons (Apply, Cancel usw.) des QTabDialog-Widget und Verknüpfen der einzelnen Button-Signale mit den entsprechenden
Slotroutinen.
Wichtige Methoden, die die Klasse QTabDialog anbietet, sind:
addTab(QWidget *child, const QString& label): fügt eine neue Seite
(child) zu einem QTabDialog-Widget hinzu. label ist dabei die Beschriftung
dieser Seite, die in der immer sichtbaren Tableiste für diese Seite (in Button-Form)
angezeigt wird. Ein Klick auf diese Beschriftung bringt dann diese Seite in den
Vordergrund. Innerhalb des Beschriftungstextes kann dabei ein Beschleuniger
angegeben werden, indem dem entsprechenden Zeichen & vorangestellt wird,
um so dem Benutzer eine schnelle Anwahl dieser Seite mittels Eingabe des ent
Alt -Taste zu ermöglichen.
sprechenden Zeichens bei gedrückter 446
6.6 Klasse QTabDialog zur Stapelung von Widgets im Karteikartenformat
Es ist darauf hinzuweisen, dass eine Seite in jedem Fall mit addTab() bzw. insertTab() in einem QTabDialog-Widget hinzuzufügen ist. Die alleinige Angabe des QTabDialog-Widget als Elternwidget bei der Erzeugung einer QWidget-Objekts (für eine Seite) reicht nicht aus. Eine solche Seite würde nicht im
QTabDialog-Widget eingeordnet und damit auch nicht angezeigt.
insertTab(QWidget *child, const QString& label, int index=1): entspricht der Methode addTab(), nur dass man hier eine Position (index)
angeben kann, an der die entsprechende Seite einzufügen ist. Die Voreinstellung
(index=-1) bedeutet, dass die entsprechende Seite am Ende eingefügt wird,
wie dies auch bei addTab() geschieht.
changeTab(QWidget *w, const QString& label): legt eine neue Beschriftung (label) für die Seite w fest.
setOkButton()
setOkButton(const QString& text): Beide Methoden fügen einen OkButton in jeder Seite des QTabDialog-Widget unten ein, wobei bei der zweiten
Methode dieser Button nicht den Text Ok, sondern den hier angegebenen text
enthält. Ist text ein null-String, wird kein Ok-Button eingeblendet. Wird der
Ok-Button angeklickt, wird automatisch das Signal applyButtonPressed()
geschickt, und die aktuellen Einstellungen aller Seiten des QTabDialog-Widget
werden übernommen. Anschließend wird dann das QTabDialog-Widget ausgeblendet.
setApplyButton()
setApplyButton(const QString& text): Beide Methoden fügen einen Apply-Button in jeder Seite des QTabDialog-Widget unten ein, wobei jedoch bei
der zweiten Methode dieser Button nicht den Text Apply, sondern eben den hier
angegebenen text enthält. Wird der Apply-Button geklickt, wird automatisch
das Signal applyButtonPressed() geschickt, und die aktuellen Einstellungen aller Seiten des QTabDialog-Widget werden übernommen. Anders als beim
Anklicken des Ok-Button bleibt hier das QTabDialog-Widget sichtbar und wird
nicht ausgeblendet.
setCancelButton()
setCancelButton(const QString& text): Beide Methoden fügen einen
Cancel-Button in jeder Seite des QTabDialog-Widgets unten ein, wobei jedoch
bei der zweiten Methode dieser Button nicht den Text Cancel, sondern eben den
hier angegebenen text enthält. Ist text ein null-String, wird kein CancelButton eingeblendet. Bei einem Klick auf den Cancel-Button wird automatisch
das Signal cancelButtonPressed() geschickt, und die Einstellungen aller
Seiten des QTabDialog-Widget werden in die Zustände zurückgesetzt, die vorlagen, als das QTabDialog-Widget eingeblendet wurde, bzw. in die Zustände,
die mit dem letzten Klicken des Apply-Button eingestellt wurden. Anschließend
wird dann das QTabDialog-Widget ausgeblendet.
setDefaultButton()
setDefaultButton(const QString& text): Beide Methoden fügen einen
Defaults-Button in jeder Seite des QTabDialog-Widget unten ein, wobei jedoch
bei der zweiten Methode dieser Button nicht den Text Defaults, sondern den hier
angegebenen text enthält. Ist text ein null-String, wird kein Defaults-Button
447
6 Vordefinierte Dialogfenster
eingeblendet. Wird der Defaults-Button geklickt, wird automatisch das Signal
defaultButtonPressed() geschickt, und die Einstellungen aller Seiten des
QTabDialog-Widget sollten auf ihre Defaults (Voreinstellungen) zurückgesetzt
werden. Wichtig ist hierbei, dass lediglich die Einstellungen im QTabDialogWidget zurückgesetzt werden sollten, diese aber noch nicht in der entsprechenden Anwendung übernommen werden sollten. Zum Übernehmen der vorgenommenen Einstellungen in der jeweiligen Applikation dienen der Ok- und Apply-Button, welche beide das Signal applyButtonPressed() schicken.
setHelpButton()
setHelpButton(const QString& text): Beide Methoden fügen einen HelpButton in jeder Seite des QTabDialog-Widget unten ein, wobei jedoch bei der
zweiten Methode der Buttontext nicht Help, sondern der angegebene text ist. Ist
text ein null-String, wird kein Help-Button eingeblendet. Wird der Help-Button
geklickt, wird das Signal helpButtonPressed() geschickt, das mit einer Slotroutine verbunden werden sollte, die entsprechende Help-Information einblendet.
showPage(QWidget *w): bringt Seite w des QTabDialog-Widgets in den Vordergrund, so dass sie sichtbar wird. Diese Methode kann bei der Verwendung
von Beschleunigern (in der Tableiste) sehr nützlich sein.
setTabEnabled(QWidget *w, bool enable): schaltet die Anwahlmöglichkeit der Seite w im QTabDialog-Widget ein (enable=true) bzw.
aus
(enable=false). Ist die Anwahl einer Seite ausgeschaltet, so wird deren Button in der Tableiste entsprechend blass dargestellt, um dem Benutzer anzuzeigen,
dass er diese Seite nicht anwählen kann.
QString tabLabel(QWidget *w): liefert die Beschriftung (in der Tableiste)
der Seite w.
setTabBar(QTabBar *tb) protected: ändert den Stil der Tableiste. Diese
Methode muss dabei unbedingt aufgerufen werden, bevor irgendwelche Seiten
zum QTabDialog-Widget hinzugefügt werden. Zum Ändern des Aussehens
der Tableiste muss dabei z. B. folgender Codeausschnitt verwendet werden:
//
QTabBar *tb = new QTabBar( this );
.... Verschiedene Stilarten (in folg. 4 Zeilen ein // entfernen)
//
tb->setShape( QTabBar::RoundedAbove );
//
tb->setShape( QTabBar::RoundedBelow );
//
tb->setShape( QTabBar::TriangularAbove );
//
tb->setShape( QTabBar::TriangularBelow );
setTabBar( tb );
Tiefergehende Informationen können Interessierte in der Qt-Online-Dokumentation bei der Klasse QTabBar nachschlagen
Die Signale, die die Klasse QTabDialog anbietet, sind:
applyButtonPressed() signal: wird geschickt, wenn der Apply- oder OkButton geklickt wird; siehe dazu auch die Beschreibung der Methoden setOkButton() und setApplyButton(). Dieses Signal sollte mit einer oder auch
mehreren Slotroutinen verbunden werden, die die entsprechenden Einstellungen
des QTabDialog-Widgets in die entsprechende Applikation übernehmen.
448
6.6 Klasse QTabDialog zur Stapelung von Widgets im Karteikartenformat
cancelButtonPressed() signal: wird geschickt, wenn der Cancel-Button
geklickt wird; siehe dazu auch die Beschreibung der Methode setCancelButton(). Dieses Signal ist automatisch mit der Methode QDialog::reject()
verbunden, welche das QTabDialog-Widget ausblendet. Da dieses Signal andeutet, dass alle vorgenommen Änderungen in den Einstellungen zu verwerfen sind, sollten die entsprechenden Einstellungen auch nicht in der Applikation
übernommen werden.
defaultButtonPressed() signal: wird geschickt, wenn der Defaults-Button
geklickt wird; siehe dazu auch die Beschreibung der Methode setDefaultButton().
helpButtonPressed() signal: wird geschickt, wenn der Help-Button
geklickt wird; siehe dazu auch die Beschreibung der Methode setHelpButton().
aboutToShow() signal: wird geschickt, bevor ein QTabDialog-Widget eingeblendet wird. Dieses Signal kann sinnvoll eingestezt werden, wenn man ein
QTabDialog-Widget nur einmal erzeugt, und immer bei Bedarf einblendet, und
ansonsten versteckt im Hintergrund hält.
currentChanged(QWidget *w) signal: wird geschickt, wenn eine neue Seite sichtbar gemacht wird.
Beispiel: Demonstrationsprogramm zur Klasse QTabDialog
Programm 6.6 blendet ein Hauptfenster mit zwei Buttons ein, zwischen denen ein
Label eingeschoben ist, das die aktuellen Einstellungen (Beantwortung der Fragen
mit entsprechender Bewertung) anzeigt (siehe Abbildung 6.18). Dieses Programm
erzeugt ein QTabDialog-Widget, das es immer bei einem Klick auf den Button
TabDialog einblendet. Dieses QTabDialog-Widget enthält auf den ersten beiden
Seiten einen kleinen Wissenstest: Auf Seite 1 eine Frage zum Allgemeinwissen (siehe links in Abbildung 6.19) und auf Seite 2 zwei Fragen zur Mathematik (siehe
rechts in Abbildung 6.19). Klickt der Benutzer auf den Übernehmen-Button, wird
seine Antwort ausgewertet und ihm im Label des Hauptfensters die Bewertung
seiner Auswahl (richtig oder falsch) angezeigt. Auf der dritten Seite bietet dieses
Abbildung 6.18: Hauptfenster des Programms 6.6
449
6 Vordefinierte Dialogfenster
Abbildung 6.19: Seite 1 und Seite 2 des QTabDialog-Widgets im Programm 6.6
QTabDialog-Widget einen Button Farbauswahl an, der bei einem Klick ein QColorDialog-Widget (siehe z. B. Abbildung 6.3) einblendet, in dem der Benutzer sich
eine Farbe auswählen kann, welche dann in einem Label unter diesem Button (sie-
Abbildung 6.20: Seite 3 des QTabDialog-Widgets im Programm 6.6
450
6.6 Klasse QTabDialog zur Stapelung von Widgets im Karteikartenformat
he Abbildung 6.20) angezeigt wird. Bei einem Klick auf den Button Übernehmen
wird diese Farbe in dem Label des Hauptfensters als Hintergrundfarbe verwendet.
In allen drei Seiten haben die einzelnen unten angezeigten Buttons die gleichen
Auswirkungen:
Ok: Die aktuellen Einstellungen aus allen drei Seiten werden übernommen und
ausgewertet. Anschließend wird das QTabDialog-Widget ausgeblendet.
Voreinstellung: Alle drei Seiten werden auf ihre Voreinstellungen zurückgesetzt
Übernehmen: Die aktuellen Einstellungen aus allen drei Seiten werden übernommen, ohne dass das QTabDialog-Widget ausgeblendet wird.
Abbrechen: Das QTabDialog-Widget wird ausgeblendet, ohne dass die vorgenommenen Einstellungen übernommen werden.
Programm 6.6 – tabdialog.cpp:
Demoprogramm zur Klasse QTabDialog
#include <qapplication.h>
#include <qvbox.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qbuttongroup.h>
#include <qradiobutton.h>
#include <qlistbox.h>
#include <qtabdialog.h>
#include <qtabbar.h>
#include <qpushbutton.h>
#include <qcolordialog.h>
QString staedte[] = { "Sydney",
const uint
QString
"Portland",
"Austra-City", "Melbourne",
"New London", "Manchester", "Kapstadt",
"Canberra",
"Jail-City",
"Downunder-City" };
staedte_zahl
"Koala-Town", "Suncity",
= sizeof(staedte) / sizeof(staedte[0]);
viertel_text[] = { "250000", "4000000", "2000000", "400000", "2500000" };
const uint
viertel_zahl
= sizeof(viertel_text) / sizeof(viertel_text[0]);
//........................................................... Klasse TabDialog
class TabDialog : public QTabDialog {
Q_OBJECT
public:
TabDialog( QString h, QString v, QString p, QColor f, QWidget *parent = 0,
const char *name = 0 ) : QTabDialog( parent, name ) {
//
//
//
.... Zum Aendern des Stils der Tableiste (in folg. Zeile // entfernen)
QTabBar
*tb = new QTabBar( this );
.... Verschiedene Stilarten (in folg. 4 Zeilen ein // entfernen)
//
tb->setShape( QTabBar::RoundedAbove );
//
tb->setShape( QTabBar::RoundedBelow );
//
tb->setShape( QTabBar::TriangularAbove );
//
//
tb->setShape( QTabBar::TriangularBelow );
.... Zum Aendern des Stils der Tableiste (in folg. Zeile // entfernen)
451
6 Vordefinierte Dialogfenster
//
setTabBar( tb );
hauptstadt = h;
viertel = v;
preis = p;
farbe = f;
setupTab1();
setupTab2();
setupTab3();
setzeAlt();
setApplyButton( "Übernehmen" );
setOkButton();
setCancelButton( "Abbrechen" );
setDefaultButton( "Voreinstellung" );
connect( this, SIGNAL( applyButtonPressed() ), SLOT( setzeUebernehmen() ) );
connect( this, SIGNAL( defaultButtonPressed() ), SLOT( setzeDefault() ) );
}
QString getHauptstadt() { return hauptstadt; }
QString getViertel()
{ return viertel;
QString getPreis()
{ return preis;
}
QColor
{ return farbe;
}
getFarbe()
}
signals:
void neuUebernommen();
private slots:
void setzeUebernehmen() {
uint
//...................... setzeUebernehmen
i;
hauptstadt = viertel = "";
for (i=0; i<cities->count(); i++)
if ( cities->isSelected( i ) )
hauptstadt = cities->text( i );
for (i=0; i<viertel_zahl; i++)
if ( frage2a[i]->isChecked() )
viertel = frage2a[i]->text();
preis = frage2b->text();
farbe = neuFarbe;
emit neuUebernommen();
}
void setzeDefault() {
//............... setzeDefault
uint i;
cities->clear();
for ( i = 0; i < staedte_zahl; i++ )
cities->insertItem( staedte[i], i );
for ( i=0; i<viertel_zahl; i++)
frage2a[i]->setChecked( false );
frage2b->setText( "" );
farbAnzeige->setPalette( QPalette( neuFarbe=Qt::white, Qt::white ) );
}
void
neueFarbe() {
//........................ neueFarbe
QColor f = QColorDialog::getColor( neuFarbe, 0 );
if ( f.isValid() )
farbAnzeige->setPalette( QPalette( neuFarbe = f, f ) );
}
private:
QListBox
*cities;
QRadioButton *frage2a[viertel_zahl];
QLineEdit
452
*frage2b;
6.6 Klasse QTabDialog zur Stapelung von Widgets im Karteikartenformat
QLabel
*farbAnzeige;
QPushButton
*farbButton;
QString
hauptstadt, viertel, preis;
QColor
farbe, neuFarbe;
void setupTab1();
void setupTab2();
void setupTab3();
void setzeAlt() {
uint
//........................ setzeAlt
i;
for ( i=0; i < cities->count(); i++ )
cities->setSelected( i, cities->text(i) == hauptstadt );
for ( i=0; i<viertel_zahl; i++)
frage2a[i]->setChecked( viertel == frage2a[i]->text() );
frage2b->setText( preis );
farbAnzeige->setPalette( QPalette( neuFarbe = farbe, farbe ) );
}
};
//.................................................................. setupTab1
void TabDialog::setupTab1() {
QVBox *tab1 = new QVBox( this );
tab1->setMargin( 5 );
tab1->setSpacing( 5 );
QLabel *l = new QLabel( "Wie heisst die Hauptstadt von Australien?", tab1 );
l->setBackgroundColor( Qt::yellow );
cities = new QListBox( tab1 );
for ( uint i = 0; i < staedte_zahl; i++ )
cities->insertItem( staedte[i], i );
cities->setPalette( QPalette( Qt::green, Qt::green ) );
addTab( tab1, "Allgemeinwissen" );
}
//.................................................................. setupTab2
void TabDialog::setupTab2() {
QVBox *tab2 = new QVBox( this );
tab2->setMargin( 5 );
tab2->setSpacing( 5 );
QButtonGroup *bg = new QButtonGroup( 1, QGroupBox::Horizontal,
"Wieviel ist eine Million geteilt durch ein Viertel?", tab2 );
for (uint i=0; i<viertel_zahl; i++) {
frage2a[i]
= new QRadioButton( viertel_text[i], bg );
frage2a[i]->setBackgroundColor( Qt::green.light( 180 ) );
}
bg->setBackgroundColor(
Qt::green.light( 180 ) );
bg->setMinimumHeight( 200 );
QLabel *l = new QLabel( tab2 );
l->setText( "Eine Flasche Wein kostet zehn Euro,\n"
"Der Wein kostet acht Euro mehr als die Flasche.\n"
"Wie teuer ist die Flasche?" );
l->setBackgroundColor( Qt::yellow );
453
6 Vordefinierte Dialogfenster
frage2b = new QLineEdit( tab2 );
addTab( tab2, "Mathematik" );
}
//.................................................................. setupTab3
void TabDialog::setupTab3() {
QVBox *tab3 = new QVBox( this );
tab3->setMargin( 50 );
tab3->setSpacing( 30 );
farbButton = new QPushButton( "Farbauswahl", tab3 );
connect( farbButton, SIGNAL( clicked() ), SLOT( neueFarbe() ) );
farbAnzeige = new QLabel( tab3 );
addTab( tab3, "Farben" );
}
//............................................................ Klasse MyWidget
class MyWidget : public QVBox {
Q_OBJECT
public:
MyWidget() : QVBox( 0, 0 ) {
QPushButton *b1 = new QPushButton( "TabDialog", this);
b1->setPalette( QPalette( Qt::green, Qt::green ) );
hauptstadt = viertel = preis = "";
farbe = Qt::white;
auswahlAnzeige = new QLabel( this );
QString
s;
s.sprintf( " Hauptstadt: %s\n"
" Eine Million geteilt durch ein Viertel: %s\n"
" Preis der Flasche: %s\n"
" Farbe (siehe Hintergrund)\n", (const char *)hauptstadt,
(const char *)viertel, (const char *)preis );
auswahlAnzeige->setText( s );
auswahlAnzeige->setPalette( QPalette( farbe, farbe ) );
auswahlAnzeige->resize( auswahlAnzeige->sizeHint() );
auswahlAnzeige->setFixedSize( 400, 200 );
auswahlAnzeige->show();
QPushButton *b2 = new QPushButton( "Beenden", this);
b2->setPalette( QPalette( Qt::red, Qt::red ) );
connect( b1, SIGNAL( clicked() ), this, SLOT( showTabDialog() ) );
connect( b2, SIGNAL( clicked() ), qApp, SLOT( quit() ) );
}
private slots:
void neuAnzeige() {
QString s;
hauptstadt = tabdialog->getHauptstadt();
viertel
= tabdialog->getViertel();
preis
= tabdialog->getPreis();
farbe
= tabdialog->getFarbe();
s.sprintf( " Hauptstadt: %s (%s)\n"
" Eine Million geteilt durch ein Viertel: %s (%s)\n"
" Preis der Flasche: %s (%s)\n"
" Farbe (siehe Hintergrund)\n",
454
6.6 Klasse QTabDialog zur Stapelung von Widgets im Karteikartenformat
(const char *)hauptstadt,
(hauptstadt=="Canberra") ? "Richtig" : "Falsch",
(const char *)viertel, (viertel=="4000000") ? "Richtig" : "Falsch",
(const char *)preis, (preis=="1") ? "Richtig" : "Falsch" );
auswahlAnzeige->setText( s );
auswahlAnzeige->setPalette( QPalette( farbe, farbe ) );
repaint();
}
void showTabDialog() {
tabdialog = new TabDialog( hauptstadt, viertel, preis, farbe );
tabdialog->resize( 450, 500 );
tabdialog->setCaption( "Wissenstest mit Farbenwahl" );
tabdialog->show();
connect( tabdialog, SIGNAL( neuUebernommen() ),
this, SLOT( neuAnzeige() ) );
}
private:
TabDialog *tabdialog;
QLabel
*auswahlAnzeige;
QString
hauptstadt, viertel, preis;
QColor
farbe;
};
//....................................................................... main
int main( int argc, char *argv[] ) {
QApplication a( argc, argv );
MyWidget *w = new MyWidget;
w->resize( 200, 100 );
w->show();
a.setMainWidget( w );
return a.exec();
}
#include "tabdialog.moc"
Abbildung 6.21: Seite 1 zur Eingabe des Namens und der Adresse
455
Index
Symbole
Überlappendes Layout . . 399
Übung
ampeltimer.cpp . . . 637
autofahr.cpp . . . . . . . 88
bildflow.cpp . . . . . . 416
canvas2.cpp . . . . . . . . 745
clipboardsend.cpp . . .
598
clipping2.cpp . . . . . 711
colordialog2.cpp . 423
countrydate.cpp . . 954
cursor2.cpp . . . . . . . . 759
customevent3.cpp . 867
datapump2.cpp . . . . 1025
datastream2.cpp . . 504
dezahexa.cpp . . . . . . . 82
dialog2.cpp . . . . . . . . 420
domplot2.cpp . . . . . 1077
dragdropcards.cpp . . .
615
dualstack.cpp . . . . . 586
dynfokus.cpp . . . . . . 820
dynlayout.cpp . . . . . 397
dynvalidator.cpp . 799
editor.cpp . . . . . . . . . 289
ehe.cpp . . . . . . . . . . . . . 103
eventfilter2.cpp . 858
filebytes.cpp . . . . . 492
filedialog2.cpp . . 431
flywindow.cpp . . . . . 727
fontdialog2.cpp . . 436
frame2.cpp . . . . . . . . . 358
functionplot2.cpp . . .
898
glpyramide.cpp . . 1084
graphik2.cpp . . . . . . . 82
graphik2.h . . . . . . . . . . 82
groupbox2.cpp . . . . . 363
httpd3.cpp . . . . . . . . 1019
image2.cpp . . . . . . . . . 770
inputdialog2.cpp . 483
josephus.cpp . . . . . . 582
lcdwandel2.cpp . . . 254
life.cpp . . . . . . . . . . . . 675
linkreis.cpp . . . . . . 691
listbox.cpp . . . . . . . . 223
listview2.cpp . . . . . 312
logging.cpp . . . . . . . . 961
lspin.cpp . . . . . . . . . . 235
manntisch.cpp . . . . . 668
mastermind.cpp . . . 377
meinls.cpp . . . . . . . . . 513
menues2.cpp . . . . . . . . 264
messagebox2.cpp . . 445
movieframes.cpp . . 785
multidownload.cpp . . .
984
multtable.cpp . . . . . 350
nsbillard.cpp . . . . 1114
ostern.cpp . . . . . . . . . 622
paintstack.cpp . . . 716
penfill.cpp . . . . . . . . 655
perl_listspin . . . . 1096
perl_malprog3 . . . . 1096
coverview.cpp . . . . . 915
pointarray2.cpp . . 547
printbild2.cpp . . . 476
progressbar2.cpp . 300
progressdialog2.cpp . . . . . . . . . 301
pythagoras.cpp . . . 705
queue.cpp . . . . . . . . . . . 58
queue2.cpp . . . . . . . . . 591
radioadd.cpp . . . . . . 879
regexp4.cpp . . . . . . . . 811
restaurant.cpp . . . 942
scrollview2.cpp . . 333
sendevent2.cpp . . . 862
snapshot2.cpp . . . . . 754
sound2.cpp . . . . . . . . . 788
splitter2.cpp . . . . . 369
tabdialog2.cpp . . . 456
timeprogress.cpp . 628
togglebutton.cpp . 216
virtfrank.cpp . . . . . . 88
waldbrand.cpp . . . . . 669
wellen.cpp . . . . . . . . . 668
widgetstack2.cpp . 373
wizard2.cpp . . . . . . . . 462
woist.cpp . . . . . . . . . . 520
woistmaus.cpp . . . . . 246
worktime.cpp . . . . . . 630
xmlplot2.cpp . . . . . 1077
xref.cpp . . . . . . . . . . . . 566
zeilzeich.cpp . . . . . 490
zeilzeich2.cpp . . . 497
zweirect.cpp . . . . . . 530
A
Animation . . . . . . . . . 733, 775
ASSERT Makro . . . . . . . . . 957
Austritts-Events . . . . . . . . 847
Auswahlwidgets . . . . . . . . 216
B
Balloon help . . . . . . . . . . . . 271
Bedingungs-Variablen . . 937
Benutzerdefinierte Events . . .
862
Benutzerdefiniertes Layout .
398
Beschleuniger . . . . . . . . . . . 258
Bildformate . . . . . . . . . . . . . 747
Browser . . . . . . . . . . . . . . . . 236
Directory . . . . . . . . . . . . . 308
Bubble help . . . . . . . . . . . . . 271
Buttongruppe . . . . . . . . . . . 363
Buttons . . . . . . . . . . . . . . . . . 204
C
C++ . . . . . . . . . . . . . . . . . . . . . . 11
<< . . . . . . . . . . . . . . . . . . . . . 27
>> . . . . . . . . . . . . . . . . . . . . . 27
1155
Index
Überladen von Funktionen
18
Zeilen-Kommentar // . 16
Abstrakte Klassen . . . . . 89
cerr . . . . . . . . . . . . . . . . . . 27
cin . . . . . . . . . . . . . . . . . . . . 27
clog . . . . . . . . . . . . . . . . . . 27
cout . . . . . . . . . . . . . . . . . . 27
Default-Argumente . . . . 17
delete . . . . . . . . . . . . . . . 36
Destruktor . . . . . . . . . . . . . 48
Frühe Bindung . . . . . . . . 83
friend . . . . . . . . . . . . . . . 65
Function overloading . . 18
Inline-Funktionen . . . . . 19
Klassen . . . . . . . . . . . . . . . . 55
Mehrfachvererbung . . . . 98
Methoden . . . . . . . . . . . . . 38
new . . . . . . . . . . . . . . . . . . . . 35
Nicht-objektorientierte
Erweiterungen . . . . . . . 16
operator . . . . . . . . . . . . . 67
Operator overloading . . 65
Polymorphismus . . . . . . 92
private . . . . . . . . . . . . . . 42
protected . . . . . . . . . . . 42
public . . . . . . . . . . . . . . . 42
Referenz-Operator & . . . 20
Späte Bindung . . . . . . . . . 86
Strukturen . . . . . . . . . . . . . 37
TemplateFunktionen . . . . . . . . . . . . 110
Klassen . . . . . . . . . . . . . . . . 105
this . . . . . . . . . . . . . . . . . . 40
C++
Variablen-Deklarationen 16
Vererbung . . . . . . . . . . . . . 72
Virtuelle
Basisklassen . . . . . . . . . . . 100
Methoden . . . . . . . . . . . . . . 86
CHECK_PTR Makro . . . . . 957
Clipboard . . . . . . . . . . . . . . 593
mit Drag-and-Drop . . . 607
Clipping (Graphik) . . . . . 708
Close-Events . . . . . . . . . . . . 849
ColorRole Typ . . . . . . . . 149
connect() . . . . . . . . . . . . . . . 130
connect() . . . . . . . . . . . . 869
Containerklasse
QList . . . . . . . . . . . . . . . . 567
Hashtabelle . . . . . . . . . . . 547
Listen . . . . . . . . . . . . . . . . 567
QArray . . . . . . . . . . . . . . 535
QAsciiCache . . . . . . . . 562
QAsciiDict . . . . . . . . . 557
QBitArray . . . . . . . . . . 540
1156
QByteArray . . . . . . . . . 540
QCache . . . . . . . . . . . . . . 559
QDict . . . . . . . . . . . . . . . . 547
QIntCache . . . . . . . . . . 562
QIntDict . . . . . . . . . . . . 557
QMap . . . . . . . . . . . . . . . . . 563
QPointArray . . . . . . . . 543
QPtrDict . . . . . . . . . . . . 557
QQueue . . . . . . . . . . . . . . 587
QStack . . . . . . . . . . . . . . 582
QStrIList . . . . . . . . . . 580
QStringList . . . . . . . . 577
QStrList . . . . . . . . . . . . 580
QValueList . . . . . . . . . 573
QValueStack . . . . . . . . 584
QVector . . . . . . . . . . . . . 540
Containerklassen . . . . . . . 521
critical() . . . . . . . . . . . 171
Cursorformen . . . . . . 747, 754
D
Danksagung . . . . . . . . . . . .
Data-Sharing . . . . . . . . . . .
Dateiauswahl-Dialogbox
Dateioperationen . . . . . . .
Datenstruktur
QList . . . . . . . . . . . . . . . .
FIFO . . . . . . . . . . . . . . . . .
Hashtabelle . . . . . . . . . . .
LIFO . . . . . . . . . . . . . . . . .
Listen . . . . . . . . . . . . . . . .
QArray . . . . . . . . . . . . . .
QAsciiCache . . . . . . . .
QAsciiDict . . . . . . . . .
QBitArray . . . . . . . . . .
QByteArray . . . . . . . . .
QCache . . . . . . . . . . . . . .
QDict . . . . . . . . . . . . . . . .
QIntCache . . . . . . . . . .
QIntDict . . . . . . . . . . . .
QMap . . . . . . . . . . . . . . . . .
QPointArray . . . . . . . .
QPtrDict . . . . . . . . . . . .
QQueue . . . . . . . . . . . . . .
QStack . . . . . . . . . . . . . .
Queue . . . . . . . . . . . . . . . .
QValueList . . . . . . . . .
QValueStack . . . . . . . .
QVector . . . . . . . . . . . . .
Stack . . . . . . . . . . . . . . . . .
Warteschlange . . . . . . . .
Datenstrukturen . . . . . . . .
Datentypen . . . . . . . . . . . . .
Datum . . . . . . . . . . . . . . . . . .
Datum und Zeit . . . . . . . .
Debugging . . . . . . . . . . . . .
VII
530
424
485
567
587
547
582
567
535
562
557
540
540
559
547
562
557
563
543
557
587
582
587
573
584
540
582
587
521
521
617
628
955
deep copy-Sharing . . . . . . 532
Dialogbox . . . . . . . . . . . . . . 417
Dateiauswahl . . . . . . . . . 424
Drucker . . . . . . . . . . . . . . 463
Einfache Eingabe . . . . . 477
Farbe . . . . . . . . . . . . . . . . . 421
Font . . . . . . . . . . . . . . . . . . 432
Fortschrittsanzeige . . . 294,
483
Karteikarten . . . . . . . . . . 446
Kombobox-Eingabe . . . 477
Message . . . . . . . . . . . . . . 436
Mitteilungen . . . . . . . . . 436
Nachrichten . . . . . . . . . . 436
Tabdialog . . . . . . . . . . . . . 446
Texteingabe . . . . . . . . . . . 477
Wizards . . . . . . . . . . . . . . 456
Zahleneingabe . . . . . . . . 477
Dialogfenster . . . . . . . . . . . 417
Directorybrowser . . . . . . . 308
Directoryoperationen . . 485,
513
Dokumentation . . . . . . . . . 117
DOM-Schnittstelle . . . . . 1053
Doppel-Pufferung . . . . . . 719
Drag-and-Drop . . . . . . . . . 598
MIME-Typen . . . . . . . . . 609
mit Clipboard . . . . . . . . 607
Drag-Events . . . . . . . . 599, 854
Drehknopf . . . . . . . . . . . . . . 225
Drop-Events . . . . . . . 599, 854
Druckerdialog . . . . . . . . . . 463
Druckerinformationen . . 466
dumpObjectInfo Funktion
959
dumpObjectTree Funktion
959
Dynamisch änderndes
Layout . . . . . . . . . . . . . 403
E
E/A-Geräte . . . . . . . . . . . . . 485
Ebuilder . . . . . . . . . . . . . . . 1142
Editor
einzeilig . . . . . . . . . . . . . . 246
mehrzeilig . . . . . . . . . . . . 247
Einfaches Layout . . . . . . . 374
Eintritts-Events . . . . . . . . . 847
Ereignisse . . . . . . . . . . . . . . 823
Event
Austritts- . . . . . . . . . . . . . 847
Benutzerdefiniert . . . . . 862
Close- . . . . . . . . . . . . . . . . 849
Custom- . . . . . . . . . . . . . . 862
Drag- . . . . . . . . . . . . 599, 854
Drop- . . . . . . . . . . . . 599, 854
Index
Eintritts- . . . . . . . . . . . . . . 847
Fokus- . . . . . . . . . . . . . . . . 841
Größenänderungs- . . . 843
Hide- . . . . . . . . . . . . . . . . . 848
Mal- . . . . . . . . . . . . . . . . . . 826
Maus- . . . . . . . . . . . . . . . . 827
Positionsänderungs- . . 845
Resize- . . . . . . . . . . . . . . . 843
Schließ- . . . . . . . . . . . . . . . 849
Senden . . . . . . . . . . . . . . . 858
Show- . . . . . . . . . . . . . . . . 849
Sichtbarkeits- . . . . . . . . . 849
Subwidget- . . . . . . . . . . . 852
Synthetisch . . . . . . . . . . . 858
Tastatur- . . . . . . . . . . . . . . 834
Timer- . . . . . . . . . . . 634, 840
Versteck- . . . . . . . . . . . . . 848
Event-Filter . . . . . . . . 823, 855
Events . . . . . . . . . . . . . . . . . . 823
Explizites Data-Sharing . 530
F
Füllbalken . . . . . . . . . . . . . . 290
einfach . . . . . . . . . . . . . . . 290
Fortschrittsanzeige . . . 294
Farb-Dialogbox . . . . . . . . . 421
Farballozierung . . . . . . . . . 639
Farbgruppen in Qt . . . . . . 149
Farbmodelle in Qt . . . . . . 146
Farbname
QColor-Objekte . . . . . . 148
vordefinierte Strings . . 148
Filter (Event) . . . . . . . 823, 855
findtr Tool . . . . . . . . . . . . 948
Flache Kopie . . . . . . . . . . . . 532
Flimmerfreie Graphik . . . 717
Fokus . . . . . . . . . . . . . . . . . . . 813
Fokus-Events . . . . . . . . . . . 841
Font-Dialogbox . . . . . . . . . 432
Form
Cursor . . . . . . . . . . . . . . . . 747
Format
Bilder . . . . . . . . . . . . . . . . 747
Pixmap . . . . . . . . . . . . . . . 747
Fortgeschrittenes Layout 377
Fortschrittsanzeige . . . . . . 483
Fortschrittsanzeige Klasse . .
294
Frames . . . . . . . . . . . . . . . . . 352
FTP Protokoll . . . . . . . . . . . 992
Funktionsplotter . . . . . . . . 882
G
Geleitwort . . . . . . . . . . . . . . . . V
Geschachteltes Layout . . 386
getOpenFileName() . 197
getSaveFileName() . 196
Größenänderungs-Events . . .
843
Graphik . . . . . . . . . . . . . . . . 639
Clipping . . . . . . . . . . . . . . 708
Doppel-Pufferung . . . . 719
Füllmuster . . . . . . . . . . . . 652
Flimmerfrei . . . . . . . . . . . 717
Geometrische Figuren 657,
670
Positionieren . . . . . . . . . 657
Rasterung . . . . . . . . . . . . 720
Text . . . . . . . . . . . . . . . . . . 660
Transformationen . . . . . 675
View-Transformationen . . .
692
Graphik
Viewport-Transformationen
698
Graphik
Window-Transformationen
692
Graphik
World-Transformationen . . .
675
Zeichenstift . . . . . . . . . . . 650
Gruppenboxen . . . . . . . . . 358
GUI-Builder . . . . . . . . . . . 1117
Ebuilder . . . . . . . . . . . . . 1142
Qt-Designer . . . . . . . . . 1117
QtArchitect . . . . . . . . . . 1142
QtEz . . . . . . . . . . . . . . . . 1142
H
Hashtabellen . . . . . . . . . . .
Hauptfenster . . . . . . . . . . .
Hide-Events . . . . . . . . . . . .
High-Level Events . . . . . .
Hilfstexte . . . . . . . . . . . . . . .
HSV-Farbmodell . . . . . . . .
HTML . . . . . . . . . . . . . . . . . .
http Protokoll . . . . . . . . . . .
547
265
848
160
271
147
236
997
I
Implizites Data-Sharing . 530
information() . . . . . . . 171
Informationswidgets . . . . 235
Internationalisierung . . . 943
Iterator
QAsciiCacheIterator .
562
QAsciiDictIterator . .
557
QCacheIterator . . . 561
QDictIterator . . . . . 552
QIntCacheIterator . . .
562
QIntDictIterator . 557
QListIterator . . . . . 571
QMapConstIterator . . .
566
QMapIterator . . . . . . 566
QPtrDictIterator . 557
QValueListConstIterator
575
QValueListIterator . .
575
K
Karteikarten . . . . . . . . . . . .
Komboboxen . . . . . . . . . . .
Kompilieren
Qt-Programme . . . . . . .
Konsistente Eingaben . . .
Kopie
flache . . . . . . . . . . . . . . . . .
tiefe . . . . . . . . . . . . . . . . . .
446
218
119
790
532
532
L
Labels . . . . . . . . . . . . . . . . . .
Laufbalken . . . . . . . . . . . . .
Layout . . . . . . . . . . . . . . . . . .
Überlappend . . . . . . . . .
Benutzerdefiniert . . . . .
Dynamisch ändernd . .
Einfach . . . . . . . . . . . . . . .
Fortgeschritten . . . . . . .
Geschachtelt . . . . . . . . . .
Tabellenform . . . . . . . . .
LCD-Anzeige . . . . . . . . . . .
linguist Tool . . . . . . . . .
Listboxen . . . . . . . . . . . . . . .
Listenansicht . . . . . . . . . . .
Low-Level Events . . . . . . .
lrelease Tool . . . . . . . . .
lupdate Tool . . . . . . . . . .
235
312
373
399
398
403
374
377
386
389
237
947
216
302
160
948
945
M
Mainwindow . . . . . . . . . . . 264
make Tool . . . . . . . . . 120, 1149
Makefile . . . . . . . . . . . . . . . 1149
Mal-Events . . . . . . . . . . . . . 826
Maus-Events . . . . . . . . . . . 827
Mauscursor . . . . . . . . . . . . . 754
Mehrsprachige
Applikationen . . . . . . 943
Menüleiste . . . . . . . . . . . . . . 259
Menüs . . . . . . . . . . . . . . . . . . 254
Kontext . . . . . . . . . . . . . . . 259
Popup . . . . . . . . . . . . . . . . 259
mergetr Tool . . . . . . . . . . 948
Messagebox . . . . . . . . . . . . 436
Meta Object Compiler . siehe
moc
1157
Index
MIME-Typen . . . . . . . . . . . 609
moc . . . . . . . . . . . . . . . . . . . . . 134
mouseDoubleClickEvent()
166
msg2qm Tool . . . . . . . . . . . . 948
Mutual Exclusion . . . . . . . 922
N
Namen von Objekten . . . 959
Netscape Plugins . . . . . . 1096
Netzwerkprogrammierung .
965
nntp Protokoll . . . . . . . . . 1000
O
Objektnamen . . . . . . . . . . . 959
Objektorientierung . . . . . . . 11
Attribute . . . . . . . . . . . . . . 55
Basisklasse . . . . . . . . . . . . 55
Exemplar . . . . . . . . . . . . . . 55
Instanz . . . . . . . . . . . . . . . . 55
Methode . . . . . . . . . . . . . . . 55
Objekt . . . . . . . . . . . . . . . . . 55
Operation . . . . . . . . . . . . . 55
Vererbung . . . . . . . . . . . . . 55
Online-Dokumentation . 117
Online-Hilfe . . . . . . . . . . . . 271
OpenGL . . . . . . . . . . . . . . . 1079
P
Paletten in Qt . . . . . . . . . . . 150
PerlQt . . . . . . . . . . . . . . . . . 1085
Pixmap-Format . . . . . . . . . 747
Plotter . . . . . . . . . . . . . . . . . . 882
Plugins . . . . . . . . . . . . . . . . 1096
Popupmenü . . . . . . . . . . . . 213
Positionsänderungs-Events .
845
progen Tool . . . . . . . . . . . 1154
Programm
dragdropclip.cpp . 608
alt_ea.cpp . . . . . . . . . . 26
ampel.cpp . . . . . . . . . . 940
ampeltimer.cpp . . . 637
analoguhr.cpp . . . . . 689
array.cpp . . . . . . . . . . 538
array2.cpp . . . . . . . . . 539
auswahlw.cpp . . . . . . 219
autofahr.cpp . . . . . . . 88
bildflow.cpp . . . . . . 416
bildformat.cpp . . . 605
bildtabelle.cpp . . 901
bildtabelle.h . . . . . 900
biszeit.cpp . . . . . . . . 630
bitarray.cpp . . . . . . 542
bitblt.cpp . . . . . . . . . 722
bitblt2.cpp . . . . . . . . 725
1158
bruch.cpp . . . . . . . . . . . 62
bruch.h . . . . . . . . . . . . . . 61
bruchio.cpp . . . . . . . . . 63
bruchio.h . . . . . . . . . . . 63
bruchrec.cpp . . . . . . . 43
bruchtyp.cpp . . . . . . . 65
bruchtyp2.cpp . . . . . . 70
button_gruppe.cpp 211
button_popup.cpp . 213
button_slot.cpp . . 874
buttons.cpp . . . . . . . . 208
canvas.cpp . . . . . . . . . 742
canvas.h . . . . . . . . . . . . 737
childevent.cpp . . . 853
cinget.cpp . . . . . . . . . . 33
cinget2.cpp . . . . . . . . . 35
cingetline.cpp . . . . . 34
cinstring.cpp . . . . . . 33
clipboardimage.cpp . .
596
clipboardsend.cpp . . .
598
clipboardtext.cpp . . .
595
clipping.cpp . . . . . . 709
colordialog.cpp . . 422
colordialog2.cpp . 423
cqueue.cpp . . . . . . . . . . 59
cstack.cpp . . . . . . . . . . 56
cursor.cpp . . . . . . . . . 757
customevent.cpp . . 863
customevent2.cpp . 865
datapump.cpp . . . . . 1023
datastream.cpp . . . 502
datastream2.cpp . . 504
datediff.cpp . . . . . . 621
datum.cpp . . . . . . . . . . . 46
destruktor.cpp . . . . . 49
dezahexa.cpp . . . . . . . 82
dial.cpp . . . . . . . . . . . . 231
dialekt1.cpp . . . . . . . 84
dialog.cpp . . . . . . . . . 419
dialog2.cpp . . . . . . . . 420
dict.cpp . . . . . . . . . . . . 551
dict2.cpp . . . . . . . . . . 551
dictiterator.cpp . 553
DigitalClock.pm . 1095
digitaluhr.cpp . . . 633
digitaluhr2.cpp . . 635
dirbrows.cpp . . . . . . 309
dirbrows.h . . . . . . . . . 308
displaystdin.cpp 1008
dom1.cpp . . . . . . . . . . 1055
domplot.cpp . . . . . . 1072
doublevalidator.cpp .
798
download.cpp . . . . . . 982
dragdropcards.cpp . . .
615
dragdropimage.cpp . . .
602
dragdropmime.cpp . . . 612
dragdroptext.cpp . 600
drawutil.cpp . . . . . . 671
dualstack.cpp . . . . . 586
dumpobject.cpp . . . 959
dynlayout.cpp . . . . . 397
dynvalidator.cpp . 799
enterleave.cpp . . . 847
entferbi.cpp . . . . . . 144
eventfilter.cpp . . 857
farbe.cpp . . . . . . . . . . 153
farbgruppe.cpp . . . 156
farbmenu.cpp . . . . . . 257
figrotate.cpp . . . . . 712
filebytes.cpp . . . . . 492
filedialog.cpp . . . 427
filedialog2.cpp . . 431
fileinfo.cpp . . . . . . 508
filetransfer.cpp . 972
flowlayout.cpp . . . 406
flowlayout.h . . . . . . 405
focusevent.cpp . . . 842
fokus1.cpp . . . . . . . . . 815
fokus2.cpp . . . . . . . . . 819
fontdialog.cpp . . . 434
fontdialog2.cpp . . 436
frame.cpp . . . . . . . . . . 354
frame2.cpp . . . . . . . . . 358
functemplate.cpp . 112
functionparser.cpp . .
896
functionplot.cpp . 885
functionplot.h . . . 883
Generierung . . . . 120, 1149
glbox.cpp . . . . . . . . . 1081
globlok.cpp . . . . . . . . . 50
graphik.cpp . . . . . . . . . 79
graphik.h . . . . . . . . . . . 77
groupbox.cpp . . . . . . 360
groupbox2.cpp . . . . . 363
hai.cpp . . . . . . . . . . . . . 102
hauptfenster.cpp . 268
hexd.cpp . . . . . . . . . . . . 501
http.cpp . . . . . . . . . . . . 997
httpd2.cpp . . . . . . . . 1012
huhn.cpp . . . . . . . . . . . . 648
ignore.cpp . . . . . . . . . . 32
image.cpp . . . . . . . . . . 765
inline.cpp . . . . . . . . . . 20
inputdialog.cpp . . 480
inputdialog2.cpp . 483
Index
intdict.cpp . . . . . . . . 558
intdict2.cpp . . . . . . 559
international.cpp . . .
949
intvalidator.cpp . 795
josephus.cpp . . . . . . 582
katzmaus.cpp . . . . . . 649
kehrzahl.cpp . . . . . . 145
keyevent.cpp . . . . . . 836
keyevent2.cpp . . . . . 839
klasstemplate.cpp . . .
109
kompilieren . . . . . . . . . . 119
layout1.cpp . . . . . . . . 375
layout2.cpp . . . . . . . . 381
layout3.cpp . . . . . . . . 382
layout4.cpp . . . . . . . . 383
layout5.cpp . . . . . . . . 385
layout6.cpp . . . . . . . . 387
layout7.cpp . . . . . . . . 392
layout8.cpp . . . . . . . . 394
lcdwandel.cpp . . . . . 243
lightdark.cpp . . . . . 152
lineedit.cpp . . . . . . 251
list.cpp . . . . . . . . . . . . 570
listiterator.cpp . 572
listspin.cpp . . . . . . 229
listview1.cpp . . . . . 306
machebi.cpp . . . . . . . . 143
main.cpp . . . . . . . . . . . . . 64
maintextsize.cpp 1124
maintextsize2.cpp . . .
1129
mainwindow.cpp . . . 284
makexmlfunction.c . . .
1047
malprog1.cpp . . . . . . 160
malprog2.cpp . . . . . . 165
malprog3.cpp . . . . . . 167
malprog4.cpp . . . . . . 173
malprog5.cpp . . . . . . 179
malprog6.cpp . . . . . . 189
map.cpp . . . . . . . . . . . . . 565
mastermind.cpp . . . 377
mehrerb1.cpp . . . . . . . 99
meinls.cpp . . . . . . . . . 513
memory.cpp . . . . . . . . . 904
menues.cpp . . . . . . . . . 261
messagebox.cpp . . . 441
messagebox2.cpp . . 445
mouseevent.cpp . . . 831
moveevent.cpp . . . . . 846
movies.cpp . . . . . . . . . 778
movies2.cpp . . . . . . . . 783
mutex.cpp . . . . . . . . . . 922
mutex2.cpp . . . . . . . . . 925
mymail.cpp . . . . . . . . 1015
networkprotocl.cpp . .
1000
neu_ea1.cpp . . . . . . . . . 26
neu_ea2.cpp . . . . . . . . . 28
neu_ea3.cpp . . . . . . . . . 28
neu_ea4.cpp . . . . . . . . . 30
noflimmer1.cpp . . . 717
noflimmer2.cpp . . . 719
noflimmer3.cpp . . . 723
noignore.cpp . . . . . . . 32
nsgifscale.cpp . . . 1112
nsgrep.cpp . . . . . . . . 1106
nsgrep.pl . . . . . . . . . 1110
nsplugin1.cpp . . . . 1102
numausg.cpp . . . . . . . . . 490
numausg2.cpp . . . . . . 496
oel.cpp . . . . . . . . . . . . . 644
ostern.cpp . . . . . . . . . 622
overlayout.cpp . . . 400
overlayout.h . . . . . . 399
overload.cpp . . . . . . . 19
painter.cpp . . . . . . . . 653
painter2.cpp . . . . . . 662
parser.cpp . . . . . . . . . 892
parser.h . . . . . . . . . . . . 891
perl_dclock . . . . . . 1094
perllcd_wandel . . 1092
perltext_groes . . 1086
philosophen.cpp . . 934
picture.cpp . . . . . . . . 771
pointarray.cpp . . . 545
pointarray2.cpp . . 547
poker.cpp . . . . . . . . . . 910
postistda.cpp . . . . . 511
potenz.cpp . . . . . . . . . 249
printbild.cpp . . . . . 473
printbild2.cpp . . . 476
printer1.cpp . . . . . . 466
printerinfo.cpp . . 467
printtext.cpp . . . . . 469
printviel.cpp . . . . . 475
progressbar.cpp . . 291
progressdialog.cpp . .
296
puzzle.cpp . . . . . . . . . 906
queue.cpp . . . . . . . . . . 588
queue2.cpp . . . . . . . . . 591
rahmenlayout.cpp . 411
rahmenlayout.h . . . 409
readerwriter.cpp . 929
reaktest.cpp . . . . . . 627
refarray.cpp . . . . . . . 24
regexp1.cpp . . . . . . . . 804
regexp2.cpp . . . . . . . . 807
regexp3.cpp . . . . . . . . 809
regexp4.cpp . . . . . . . . 811
rennen.cpp . . . . . . . . . 920
resizeevent.cpp . . 844
richtext.cpp 239, 1075
schachbrett.cpp . . 693
schachbrett2.cpp . 699
schieb_balk.cpp . . . . . . 129
scrollbar.cpp . . . . . 329
scrollbar.h . . . . . . . . 327
scrollview.cpp . . . 322
sendevent.cpp . . . . . 860
setviewport.cpp . . 700
showhideclose.cpp . . .
850
signal.cpp . . . . . . . . . 878
signalmapper.cpp . 876
sinus.cpp . . . . . . . . . . 695
sinusfunc.cpp . . . . . 888
snapshot.cpp . . . . . . 752
sound.cpp . . . . . . . . . . 787
spiro.cpp . . . . . . . . . . 696
splitter.cpp . . . . . . 367
splitter2.cpp . . . . . 369
stack.cpp . . . . . . . . . . 583
stringlist.cpp . . . 579
strlist.cpp . . . . . . . . 581
superhirn.cpp . . . . . . 52
tabdialog.cpp . . . . . 451
tabdialog2.cpp . . . 456
table.cpp . . . . . . . . . . 347
tableview . . . . . . . . . . 338
tableview.h . . . . . . . . 336
tausch.cpp . . . . . . . . . . 23
text_groes.cpp . . . 132
textsizeimpl.cpp . . . . .
1129, 1131
textsizeimpl.h . . 1129
thread.cpp . . . . . . . . . 918
tier.cpp . . . . . . . . . . . . . 91
tier.h . . . . . . . . . . . . . . . 90
timeprogress.cpp . 628
tooltip.cpp . . . . . . . . 272
tooltip2.cpp . . . . . . 276
transform.cpp . . . . . 680
treesize.cpp . . . . . . 519
validator.cpp . . . . . 792
valuelist.cpp . . . . . 577
valuestack.cpp . . . 585
virtfrank.cpp . . . . . . 89
welchtag.cpp . . . . . . 620
widgetstack.cpp . . 371
widgetstack2.cpp . 373
wizard.cpp . . . . . . . . . 458
wizard2.cpp . . . . . . . . 462
woist.cpp . . . . . . . . . . 520
worktime.cpp . . . . . . 630
1159
Index
wortstat.cpp . . . . . . 555
xform.cpp . . . . . . . . . . 685
xml1.cpp . . . . . . . . . . 1029
xmlplot.cpp . . . . . . 1043
xmlrichtext.cpp . 1050
xref.cpp . . . . . . . . . . . . 566
zeigbild.cpp . . . . . . 238
zeilzeich.cpp . . . . . 490
zeilzeich2.cpp . . . 497
zeitadd.cpp . . . . . . . . 625
zoo.cpp . . . . . . . . . . . . . . 93
zoo.h . . . . . . . . . . . . . . . . . 93
zwei_buttons.cpp . 124
zweirect.cpp . . . . . . 530
Protokoll
FTP . . . . . . . . . . . . . . . . . . 992
http . . . . . . . . . . . . . . . . . . 997
nntp . . . . . . . . . . . . . . . . . 1000
Q
QApplication Klasse . 125
QArray Klasse . . . . . . . . . 535
QAsciiCache Klasse . . . 562
QAsciiCacheIterator
Klasse . . . . . . . . . . . . . . 562
QAsciiDict Klasse . . . . 557
QAsciiDictIterator
Klasse . . . . . . . . . . . . . . 557
QBitArray Klasse . . . . . 540
QBitmap Klasse . . . . . . . . 751
QBitVal Klasse . . . . . . . . 541
QBoxLayout Klasse . . . . 378
QBrush Klasse . . . . . . . . . 652
QBuffer Klasse . . . . . . . . 491
QButtonGroup Klasse . 873
QButtonGroup Klasse . 206,
363
QByteArray Klasse . . . . 540
QCache Klasse . . . . . . . . . 559
QCacheIterator Klasse . . .
561
QCanvas Klasse . . . . . . . . 727
QCanvasPolygonalItem
Klasse . . . . . . . . . . . . . . 733
QCanvasEllipse Klasse . . .
732
QCanvasItem Klasse . . . 729
QCanvasLine Klasse . . . 731
QCanvasPixmap Klasse 734
QCanvasPixmapArray
Klasse . . . . . . . . . . . . . . 735
QCanvasPolygon Klasse . . .
732
QCanvasRectangle Klasse
731
QCanvasSprite Klasse 733
1160
QCanvasText Klasse . . . 734
QCanvasView Klasse . . . 735
QChar Klasse . . . . . . . . . . . 137
QCheckBox Klasse . . . . . 205
QChildEvent Klasse . . . 853
QClipboard Klasse . . . . 594
QCloseEvent Klasse . . . 849
QColor Klasse . . . . . 146, 639
QColor-Objekte
(vordefiniert) . . . . . . . 148
QColorDialog Klasse . 421
QColorDrag Klasse . . . . 606
QColorGroup Klasse . . . 149
QComboBox Klasse . . . . . 218
QCString Klasse . . . . . . . 604
QCursor Klasse . . . . . . . . 754
QCustomEvent Klasse . 863
QDataPump Klasse . . . . 1023
QDataSink Klasse . . . . 1022
QDataSource Klasse . 1021
QDataStream Klasse . . . 498
QDate Klasse . . . . . . . . . . . 617
QDateTime Klasse . . . . . 628
qDebug Funktion . . . . . . . 955
QDial Klasse . . . . . . . . . . . 225
QDialog Klasse . . . . . . . . 418
QDict Klasse . . . . . . . . . . . 547
QDictIterator Klasse 552
QDir Klasse . . . . . . . . . . 513
QDns Klasse . . . . . . . . . . . 1009
QDomAttr Klasse . . . . . . 1063
QDomCDATASection Klasse
1066
QDomCharacterData
Klasse . . . . . . . . . . . . . 1064
QDomComment Klasse . 1065
QDomDocument Klasse 1061
QDomDocumentFragment
Klasse . . . . . . . . . . . . . 1067
QDomDocumentType Klasse
1067
QDomElement Klasse . 1062
QDomEntity Klasse . . . 1068
QDomEntityReference
Klasse . . . . . . . . . . . . . 1068
QDomImplementation
Klasse . . . . . . . . . . . . . 1070
QDomNamedNodeMap Klasse
1070
QDomNode Klasse . . . . . . 1057
QDomNodeList Klasse 1071
QDomNotation Klasse 1069
QDomProcessingInstruction
Klasse . . . . . . . . . . . . . 1069
QDomText Klasse . . . . . . 1066
QDoubleValidator Klasse
796
QDragEnterEvent Klasse .
854
QDragEnterEvent Klasse .
607
QDragLeaveEvent Klasse .
855
QDragMoveEvent Klasse . . .
607, 855
QDragObject Klasse 603
QDropEvent Klasse 607, 855
QEucJpCodec Klasse . . . 954
QEucKrCodec Klasse . . . 954
QEvent Klasse . . . . . . . . . 824
qFatal Funktion . . . . . . . 956
QFile Klasse . . . . . . . . . . . 487
QFileDialog Klasse . . . 424
QFileIconProvider
Klasse . . . . . . . . . . . . . . 427
QFileInfo Klasse . . . . . 506
QFileInfoList Klasse 516
QFileInfoListIterator
Klasse . . . . . . . . . . . . . . 516
QFilePreview Klasse . 427
QFocusData Klasse . . . . 818
QFocusEvent Klasse . . . 841
QFont Klasse . . 127, 201, 432
QFontDialog Klasse . . . 432
QFontInfo Klasse . . . . . 534
QFontMetrics Klasse . 469,
534
QFrame Klasse . . . . . . . . . 352
QFtp Klasse . . . . . . . . . . . . 992
QGbkCodec Klasse . . . . . 954
QGLContext Klasse . . . 1080
QGLFormat Klasse . . . . 1081
QGLWidget Klasse . . . . 1080
QGrid Klasse . . . . . . . . . . . 374
QGridLayout Klasse . . . 389
QGroupBox Klasse . . . . . 358
QHBox Klasse . . . . . . . . . . . 374
QHBoxLayout Klasse . . . 378
QHeader Klasse . . . . . . . . 344
QHideEvent Klasse . . . . 848
QHostAddress Klasse 1008
QIconDrag Klasse . 603, 607
QIconDragItem Klasse 607
QIconSet Klasse . . 344, 534
QIconView Klasse . . . . . 607
QImage Klasse . . . . . . . . . 759
QImageDrag Klasse . . . . 604
QImageIO Klasse . . . . . . . 764
QInputDialog Klasse . 477
qInstallMsgHandler
Funktion . . . . . . . . . . . 956
Index
QIntCache Klasse . . . . . 562
QIntCacheIterator
Klasse . . . . . . . . . . . . . . 562
QIntDict Klasse . . . . . . . 557
QIntDictIterator Klasse
557
QIntValidator Klasse 794
QIODevice Klasse . . . . . 485
QIODeviceSource Klasse .
1021
QJisCodec Klasse . . . . . 954
QKeyEvent Klasse . . . . . 834
QLabel Klasse . . . . . 127, 235
QLayoutItem Klasse . . 399,
404
QLayoutIterator Klasse .
399
QLCDNumber Klasse 129, 237
QLineEdit Klasse . . . . . 246
QList Klasse . . . . . . . . . . . 567
QListBox Klasse . . . . . . . 216
QListIterator Klasse 571
QListView Klasse . . . . . 302
QListViewItem Klasse 304
QListViewItemIterator
Klasse . . . . . . . . . . . . . . 305
QLocalFs Klasse . . . . . . . 993
qm2ts Tool . . . . . . . . . . . . . 948
QMap Klasse . . . . . . . . . . . . 563
QMapConstIterator
Klasse . . . . . . . . . . . . . . 566
QMapIterator Klasse . 566
QMenuBar Klasse . . . . . . . 169
QMenuData Klasse . 170, 255
QMessageBox Klasse . . 171,
436
QMotifStyle Klasse . . . 203
QMouseEvent Klasse . . . 828
QMoveEvent Klasse . . . . 845
QMovie Klasse . . . . . . . . . 775
QMultiLineEdit Klasse . . .
247
QMutex Klasse . . . . . . . . . 922
QNetworkOperation
Klasse . . . . . . . . . . . . . . 978
QNetworkProtocol Klasse
984, 990
QNPInstance Klasse . 1099
QNPlugin Klasse . . . . . . 1097
QNPStream Klasse . . . . 1101
QNPWidget Klasse . . . . 1100
QObject Klasse . . . . . . . . 126
QObject Klasse . . . . . . . . 132
QPaintDeviceMetrics
Klasse . . . . . . . . . . . . . . 466
QPainter Klasse . . . . . . . 639
QPainter-Zustand
Sichern . . . . . . . . . . . . . . . 712
Wiederherstellen . . . . . 712
QPaintEvent Klasse . . . 827
QPalette Klasse . . . . . . . 150
QPen Klasse . . . . . . . . . . . . 650
QPicture Klasse . . . . . . . 770
QPixmap Klasse . . . . . . . . 748
QPixmapCache Klasse . 751
QPoint Klasse . . . . . . . . . 523
QPointArray Klasse 543
QPopupMenu Klasse . . . . 168
QPrinter Klasse . . . . . . . 463
QProgressBar Klasse . 290
QProgressDialog Klasse .
294, 483
QPtrDict Klasse . . . . . . . 557
QPtrDictIterator Klasse
557
QPushButton Klasse . . . 204
QQueue Klasse . . . . . . . . . 587
QRadioButton Klasse . 205
QRangeControl Klasse 225
QRect Klasse . . . . . . . . . . . 527
QRegExp Klasse . . . . . . . . 799
QRegion Klasse . . . . . . . . 708
QResizeEvent Klasse . 844
QRgb Klasse . . . . . . . . . . . . 421
QScrollBar Klasse . . . . 326
QScrollView Klasse . . 172,
312
QSemaphore Klasse . . . . 927
QSemiModal Klasse . . . . 294
QServerSocket Klasse 996
QShowEvent Klasse . . . . 849
QSignal Klasse . . . . . . . . 877
QSignalMapper Klasse 875
QSize Klasse . . . . . . . . . . . 525
QSjisCodec Klasse . . . . 954
QSlider Klasse . . . . 128, 224
QSocket Klasse . . . . . . . . 993
QSocketDevice Klasse 996
QSocketNotifier Klasse .
1005
QSound Klasse . . . . . . . . . 786
QSpinBox Klasse . . . . . . . 227
QSplitter Klasse . . . . . 363
QStack Klasse . . . . . . . . . 582
QStoredDrag Klasse . . . 615
QStoredDrag Klasse . . . 603
QStrIList Klasse . . . . . 580
QString Klasse . . . . . . . . 137
QStringList Klasse . . . 577
QStrList Klasse . . . . . . . 580
QStyle Klasse . . . . . . . . . 203
Qt-Designer . . . . . . . . . . . 1117
Qt-Referenz . . . . . . . . . . . . . 117
QTabDialog Klasse . . . . 446
QTable Klasse . . . . . . . . . 341
QTableItem Klasse . . . . 345
QTableSelection Klasse .
345
QTableView Klasse . . . . 333
QtArchitect . . . . . . . . . . . . 1142
QTextBrowser Klasse . 236
QTextCodec Klasse . . . . 954
QTextDrag Klasse . . . . . 604
QTextStream Klasse . . . 493
QTextView Klasse . . . . . 236
QtEz . . . . . . . . . . . . . . . . . . . 1142
QThread Klasse . . . . . . . . 917
QTime Klasse . . . . . . . . . . . 623
QTimer Klasse . . . . . . . . . 632
QTimerEvent Klasse . . . 840
QTimerEvent Klasse . . . 634
QToolButton Klasse . . . 267
QToolTipGroup Klasse 271
QTranslator Klasse . . . 948
QTsciiCodec Klasse . . . 954
QUriDrag Klasse . . . . . . . 615
QUrl Klasse . . . . . . . . . . . . 974
QUrlInfo Klasse . . . . . . . 976
QUrlOperator Klasse . 965
QValidator Klasse . . . . 790
QValueList Klasse . . . . 573
QValueListConstIterator
Klasse . . . . . . . . . . . . . . 575
QValueListIterator
Klasse . . . . . . . . . . . . . . 575
QValueStack Klasse . . . 584
QVBox Klasse . . . . . . . . . . . 374
QVBoxLayout Klasse . . . 378
QVector Klasse . . . . . . 540
QWaitCondition Klasse . . .
937
qWarning Funktion . . . . 955
QWhatsThis Klasse . . . . 271
QWheelEvent Klasse . . . 830
QWidget Klasse . . . . . . . . 125
QWidgetStack Klasse . 370
QWindowsStyle Klasse 203
QWizard Klasse . . . . . . . . 456
QWMatrix Klasse . . . . . . . 688
QXmlAttributes Klasse . . .
1038
QXmlContentHandler
Klasse . . . . . . . . . . . . . 1032
QXmlDeclHandler Klasse .
1036
QXmlDefaultHandler
Klasse . . . . . . . . . . . . . 1037
1161
Index
QXmlDTDHandler Klasse . . .
1035
QXmlEntityResolver
Klasse . . . . . . . . . . . . . 1035
QXmlErrorHandler Klasse
1034
QXmlInputSource Klasse .
1040
QXmlLexicalHandler
Klasse . . . . . . . . . . . . . 1037
QXmlLocator Klasse . 1039
QXmlNameSpaceSupport
Klasse . . . . . . . . . . . . . 1042
QXmlParseException
Klasse . . . . . . . . . . . . . 1035
QXmlReader Klasse . . . 1040
QXmlSimpleReader Klasse
1041
R
Rasterung (Graphik) . . . .
Referenz . . . . . . . . . . . . . . . .
Reguläre Ausdrücke . . . .
Resize-Events . . . . . . . . . . .
RGB-Farbmodell . . . . . . . .
Richtext . . . . . . . . . . . . . . . .
720
117
799
843
146
236
S
SAX2-Schnittstelle . . . . . 1027
Schiebebalken . . . . . . 128, 224
Schließ-Events . . . . . . . . . . 849
Screenshots . . . . . . . . . . . . . 752
Scrollviews . . . . . . . . . . . . . 312
Semaphore . . . . . . . . . . . . . 927
setGeometry() . . . . . . . 202
setMaximumHeight() 202
setMaximumSize() . . . 202
setMinimumHeight() 202
setMinimumSize() . . . 202
setMinimumWidth() . 202
setPalette() . . . . . . . . 201
setStyle() . . . . . . . . . . . 203
shallow copy-Sharing . . . 532
Show-Events . . . . . . . . . . . 849
Sichtbarkeits-Events . . . . 849
Signal-Slot-Konzept . . . . 128,
135, 869
sizeHint() . . . . . . . . . . . 202
Sound . . . . . . . . . . . . . . . . . . 786
1162
Spinboxen . . . . . . . . . . . . . .
Splitter . . . . . . . . . . . . . . . . .
Statuszeile . . . . . . . . . . . . . .
Strings in Qt . . . . . . . . . . . .
Subwidget-Events . . . . . .
Synthetische Events . . . . .
227
363
279
137
852
858
T
Tabdialog . . . . . . . . . . . . . . . 446
Tabelle
Einfach . . . . . . . . . . . . . . . 333
Kalkulation . . . . . . . . . . . 341
Komfortabel . . . . . . . . . . 341
Kopf . . . . . . . . . . . . . . . . . . 344
Spreadsheet . . . . . . . . . . 341
Tabelle von Bildern . . . . . 898
Tastatur-Events . . . . . . . . . 834
Tastaturfokus . . . . . . . . . . . 813
Testausgaben . . . . . . . . . . . 955
Textanzeige
HTML . . . . . . . . . . . . . . . . 236
Komfortabel . . . . . . . . . . 236
Richtext . . . . . . . . . . . . . . 236
Textbrowser . . . . . . . . . . . . 236
Texteingabe . . . . . . . . . . . . . 246
Threads . . . . . . . . . . . . . . . . . 917
Tiefe Kopie . . . . . . . . . . . . . 532
Timer . . . . . . . . . . . . . . . . . . . 632
Timer-Events . . . . . . . 634, 840
tmake Tool . . . . . . . . 115, 1149
tmake Tool . . . . . . . . . . . . . 120
Tool
Ebuilder . . . . . . . . . . . . . 1142
findtr . . . . . . . . . . . . . . 948
linguist . . . . . . . . . . . . 947
lrelease . . . . . . . . . . . . 948
lupdate . . . . . . . . . . . . . 945
make . . . . . . . . . . . . 120, 1149
mergetr . . . . . . . . . . . . . 948
msg2qm . . . . . . . . . . . . . . 948
progen . . . . . . . . . . . . . 1154
qm2ts . . . . . . . . . . . . . . . . 948
Qt-Designer . . . . . . . . . 1117
QtArchitect . . . . . . . . . . 1142
QtEz . . . . . . . . . . . . . . . . 1142
tmake . . . . . . 115, 120, 1149
uic . . . . . . . . . . . . . . . . . 1124
Tooltips . . . . . . . . . . . . . . . . . 271
Transformationen (Graphik)
675
U
uic Compiler . . . . . . . . . 1124
Unicode . . . . . . . . . . . . . . . . 943
Unified Modeling Language
(UML) . . . . . . . . . . . . . . . 13
URI-Referenzen . . . . . . . . . 615
V
Validierung von Eingaben . .
790
Versteck-Events . . . . . . . . . 848
View-Transformationen
(Graphik) . . . . . . . . . . 692
Viewport-Transformationen
(Graphik) . . . . . . . . . . 698
Vordefinierte Datentypen . . .
521
Vordefinierte Dialogfenster .
417
Vordefinierte
Datenstrukturen . . . . 521
W
warning() . . . . . . . . . . . . 171
Werkzeugleiste . . . . . . . . . 267
Widget
Begriff . . . . . . . . . . . . . . . . 117
Widgetstack . . . . . . . . . . . . 370
Window-Transformationen
(Graphik) . . . . . . . . . . 692
Wizards . . . . . . . . . . . . . . . . 456
World-Transformationen
(Graphik) . . . . . . . . . . 675
X
XML
DOM . . . . . . . . . . . . . . . . 1053
SAX2 . . . . . . . . . . . . . . . . 1027
XML-Parser . . . . . . . . . . . 1027
Z
Zeichenketten in Qt . . . . .
Zeit . . . . . . . . . . . . . . . . . . . . .
Zeit und Datum . . . . . . . .
Zeitschaltuhren . . . . . . . . .
Zuordnung von Widgets
137
623
628
632
352

Documentos relacionados