Getting Started/de: Difference between revisions
No edit summary |
m (Korrektur h3.) |
||
(7 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
diese Seite in: | diese Seite in: [http://doc.qt.io/qt-4.8/gettingstartedqt.html en], [http://wiki.qt.io/GettingStartedQt_Spanish es], [http://wiki.qt.io/GettingStartedWithQtRussian ru], [http://wiki.qt.io/GettingStartedQtPolish pl], [http://wiki.qt.io/gettingStartedPortuguese pt], [http://wiki.qt.io/GettingStartedQtDutch nl] | ||
= Schnelleinstieg in die Programmierung mit Qt = | = Schnelleinstieg in die Programmierung mit Qt = | ||
Willkommen in der Welt von Qt des | Willkommen in der Welt von Qt des plattformübergreifenden GUI Framework. In dieser "Schnelleinstiegs"-anleitung lehren wir grundlegendes Qt Wissen durch das Implementieren einer einfachen Notepad Anwendung. Nach dem Durchlesen dieser Anleitung sind Sie soweit in die Übersichten und API Dokumentation einzutauchen und die Informationen zu finden, die Sie für die Anwendung brauchen, die Sie entwickeln. | ||
== Hallo Notepad == | == Hallo Notepad == | ||
Line 11: | Line 10: | ||
In diesem ersten Beispiel werden wir ein einfaches Texteingabefeld erstellen und in einem Fenster auf dem Desktop anzeigen. Das stellt das einfachste Qt Programm mit einer Benutzeroberfläche dar. | In diesem ersten Beispiel werden wir ein einfaches Texteingabefeld erstellen und in einem Fenster auf dem Desktop anzeigen. Das stellt das einfachste Qt Programm mit einer Benutzeroberfläche dar. | ||
[[Image:http://doc.qt.io/qt-4.8/images/gs1.png|Texteingabefenster]] | |||
Hier ist der Code: | Hier ist der Code: | ||
Line 18: | Line 17: | ||
#include <QTextEdit> | #include <QTextEdit> | ||
int main(int | int main(int argc, char *argv[]) | ||
{ | { | ||
QApplication app(argv | QApplication app(argc, argv); | ||
QTextEdit textEdit; | QTextEdit textEdit; | ||
Line 28: | Line 27: | ||
} | } | ||
</code> | </code> | ||
Zeile 6 erstellt ein QApplication Objekt. Dieses Objekt behandelt anwendungsweit Ressourcen und ist notwendig für eine Qt Anwendung mit einer grafischen Benutzeroberfläche. Der Konstruktor benötigt argv | Lassen Sie uns mal Zeile für Zeile durch den Code gehen. In den ersten beiden Zeilen binden wir die Headerdateien für [http://doc.qt.io/qt-4.8/qapplication.html QApplication] und [http://doc.qt.io/qt-4.8/qtextedit.html QTextEdit] ein, die beide Klassen darstellen, die wir für dieses Beispiel benötigen. Alle Qt Klassen haben eine Headerdatei, die den Namen der Klasse trägt. | ||
Zeile 6 erstellt ein QApplication Objekt. Dieses Objekt behandelt anwendungsweit Ressourcen und ist notwendig für eine Qt Anwendung mit einer grafischen Benutzeroberfläche. Der Konstruktor benötigt argc und argv, weil Qt ein Paar Kommandozeilenargumente entgegen nehmen kann. | |||
Zeile 8 erstellt ein QTextEdit Objekt. Eine Texteingabefeld ist ein visuelles Element einer Benutzeroberfläche. In Qt nennen wir solche Elemente Widgets. Beispiele anderer Widgets sind Scrollbalken, Labels und Radiobuttons. Ein Widget kann auch ein Container für andere Widgets sein; ein Dialog oder ein Hauptanwendungsfenster zum Beispiel. | Zeile 8 erstellt ein QTextEdit Objekt. Eine Texteingabefeld ist ein visuelles Element einer Benutzeroberfläche. In Qt nennen wir solche Elemente Widgets. Beispiele anderer Widgets sind Scrollbalken, Labels und Radiobuttons. Ein Widget kann auch ein Container für andere Widgets sein; ein Dialog oder ein Hauptanwendungsfenster zum Beispiel. | ||
Zeile 9 zeigt das Texteingabefeld auf dem Bildschirm in seinem eigenen Fenster. Da Widgets auch als Container verwendet werden können (z. B. ein | Zeile 9 zeigt das Texteingabefeld auf dem Bildschirm in seinem eigenen Fenster. Da Widgets auch als Container verwendet werden können (z.B. ein [http://doc.qt.io/qt-4.8/qmainwindow.html QMainWindow], das Toolbars, Menüs, Statuszeile und ein paar andere Widgets), ist es möglich ein einzelnes Widget in eigenem Fenster anzuzeigen. Widgets sind standardmäßig nicht sichtbar; die Funktion [http://doc.qt.io/qt-4.8/qwidget.html#show show()] macht sie sichtbar. | ||
Zeile 11 | Zeile 11 lässt [http://doc.qt.io/qt-4.8/qapplication.html QApplication] in die Ereignisschleife eintreten. Solange eine Qt Anwendung läuft werden Ereignisse generiert und an die Widgets der Anwendung gesendet. Beispiele solcher Ereignisse sind Mausklicks oder Tastatureingaben. Wenn Sie einen Text in das Texteingabefeld eintippen empfängt es Tastatureingabe Ereignisse und beantwortet diese in dem es den eingegebenen Text darstellt. | ||
Um die Anwendung auszuführen öffnen Sie die Kommandozeile und gehen zum Verzeichnis in dem Sie die .cpp Dateien des Programms liegen haben. Folgende Shell Kommandos übersetzen und erstellen das Programm. | Um die Anwendung auszuführen öffnen Sie die Kommandozeile und gehen zum Verzeichnis in dem Sie die .cpp Dateien des Programms liegen haben. Folgende Shell Kommandos übersetzen und erstellen das Programm. | ||
<code> | <code> | ||
qmake -project | qmake -project | ||
Line 44: | Line 45: | ||
make | make | ||
</code> | </code> | ||
Das wird eine ausführbare Datei im part1 Verzeichnis erstellen (unter Windows werden Sie u. U. nmake anstatt make verwenden müssen. Ferner wird die ausführbare Datei in part1/debug oder part1/release erstellt). qmake is Qts Erstellprogramm, das eine Konfigurationsdatei entgegen nimmt. qmake erstellt diese für uns, wenn das Argument -project übergeben wird. Mit der Konfigurationsdatei (mit der Endung .pro) erstellt qmake eine make Datei, das das Programm für Sie erstellt. Wir werden uns später ansehen wie man eigene .pro Datei schreibt. | Das wird eine ausführbare Datei im part1 Verzeichnis erstellen (unter Windows werden Sie u. U. nmake anstatt make verwenden müssen. Ferner wird die ausführbare Datei in part1/debug oder part1/release erstellt). qmake is Qts Erstellprogramm, das eine Konfigurationsdatei entgegen nimmt. qmake erstellt diese für uns, wenn das Argument -project übergeben wird. Mit der Konfigurationsdatei (mit der Endung .pro) erstellt qmake eine make Datei, das das Programm für Sie erstellt. Wir werden uns später ansehen wie man eigene .pro Datei schreibt. | ||
=== Mehr erfahren === | |||
|''. Über |''. Hier | | |''. Über |''. Hier | | ||
| Widgets und Fenstergeometrie | | | Widgets und Fenstergeometrie | [http://doc.qt.io/qt-4.8/application-windows.html Window and Dialog Widgets] | | ||
| Ereignisse und ihre Behandlung | | | Ereignisse und ihre Behandlung | [http://doc.qt.io/qt-4.8/eventsandfilters.html The Event System] | | ||
In einer echten Anwendung werden Sie mehr als nur ein Widget benötigen. Wir werden nun einen | == Einen Beenden Knopf hinzufügen == | ||
In einer echten Anwendung werden Sie mehr als nur ein Widget benötigen. Wir werden nun einen [http://doc.qt.io/qt-4.8/qpushbutton.html QPushButton] unter das Texteingabefeld anbringen. Der Knopf wird die Notepad Anwendung beim Betätigen (z. B. durch das Klicken mit der Maus) beenden. | |||
[[Image:http://doc.qt.io/qt-4.8/images/gs2.png|Eingabefeld mit Beenden Knopf]] | |||
Lassen Sie uns mal einen Blick auf den Code werfen: | Lassen Sie uns mal einen Blick auf den Code werfen: | ||
<code> | <code> | ||
#include < | #include <QApplication> | ||
#include <QLayout> | |||
#include <QTextEdit> | |||
#include <QPushButton> | |||
int main(int | int main(int argc, char *argv[]) | ||
{ | { | ||
QApplication app(argv | QApplication app(argc, argv); | ||
QTextEdit textEdit; | QTextEdit *textEdit = new QTextEdit; | ||
QPushButton quitButton("Quit"); | QPushButton *quitButton = new QPushButton("&Quit"); | ||
QObject::connect( | QObject::connect(quitButton, SIGNAL (clicked()), qApp, SLOT (quit())); | ||
QVBoxLayout layout; | QVBoxLayout *layout = new QVBoxLayout; | ||
layout | layout->addWidget(textEdit); | ||
layout | layout->addWidget(quitButton); | ||
QWidget window; | QWidget window; | ||
window.setLayout(& | window.setLayout(&layout); | ||
window.show(); | window.show(); | ||
Line 82: | Line 86: | ||
} | } | ||
</code> | </code> | ||
Zeile | Zeile 13 verwendet Qts Signals and Slots Mechanismus um die Anwendung beim Drücken des '''Beenden Knopf''' zu schließen. Ein Slot ist eine Funktion, die durch die Verwendung ihres Namens (in Form einer Zeichenkette) zu Laufzeit aufgerufen werden kann. Ein Signal ist eine Funktion die, wenn aufgerufen, alle dazu registrierten Slots aufruft; wir nennen es einen Slot mit einem Signal verbinden und ein Signal erzeugen. | ||
[http://doc.qt.io/qt-4.8/qcoreapplication.html#quit quit()] ist ein Slot der [http://doc.qt.io/qt-4.8/qapplication.html QApplication], der die Anwendung beendet. [http://doc.qt.io/qt-4.8/qabstractbutton.html#clicked clicked()] ist ein Signal, das [http://doc.qt.io/qt-4.8/qpushbutton.html QPushButton] erzeugt, wenn der Knopf gedrückt wird. Die statische [http://doc.qt.io/qt-4.8/qobject.html#connect QObject::connect()] Funktion sorgt für die Verbindung des Slots und des Signals. SIGNAL () und SLOT() sind zwei Makros, die die Funktionssignatur des Signal bzw. Slot entgegennehmen, die verbunden werden sollen. Ferner müssen wir die Zeiger der Objekte übergeben, das das Signal sendet bzw. empfängt. | |||
Zeile | Zeile 15 erzeugt ein [http://doc.qt.io/qt-4.8/qvboxlayout.html QVBoxLayout]. Wie bereits erwähnt, können Widgets auch andere Widgets enthalten. Es ist möglich die Abgrenzungen (Größe und Position) eines Kindwidgets direkt zu setzen. Jedoch ist es einfacher ein Layout zu verwenden. Ein Layout verwaltet die Abgrenzungen der Kindwidgets. Beispielsweise positioniert [http://doc.qt.io/qt-4.8/qvboxlayout.html QVBoxLayout] die Kindelemente vertikal untereinander. | ||
Zeile | Zeile 16 und 17 fügen das Texteingabefeld und den Knopf dem Layout hinzu. In Zeile 20 setzen wir das Layout eines Widgets. | ||
=== Mehr erfahren === | |||
|''. Über |''. Hier | | |''. Über |''. Hier | | ||
| Signale und Slots | | | Signale und Slots | [http://doc.qt.io/qt-4.8/signalsandslots.html Signals & Slots] | | ||
| Layouts | | | Layouts | [http://doc.qt.io/qt-4.8/layout.html Layout Management], [http://doc.qt.io/qt-4.8/widgets-and-layouts.html Widgets and Layouts], [http://doc.qt.io/qt-4.8/examples-layouts.html Layout Examples] | | ||
| Widgets die Qt bereitstellt | | | Widgets die Qt bereitstellt | [http://doc.qt.io/qt-4.8/gallery.html Qt Widget Gallery], [http://doc.qt.io/qt-4.8/examples-widgets.html Widget Examples] | | ||
Wenn der Benutzer die Anwendung beenden will ist es u. U. erwünscht einen Dialog anzuzeigen, der sicherstellt, | == QWidget Unterklassen erstellen == | ||
Wenn der Benutzer die Anwendung beenden will ist es u. U. erwünscht einen Dialog anzuzeigen, der sicherstellt, dass der Benutzer die Anwendung tatsächlich beenden möchte. In diesem Beispiel erstellen wir eine [http://doc.qt.io/qt-4.8/qwidget.html QWidget] Unterklasse und fügen einen Slot der Klasse hinzu, den wir mit dem '''Beenden Knopf''' verknüpfen. | |||
[[Image:http://doc.qt.io/qt-4.8/images/gs3.png|QWidget Unterklasse]] | |||
Lassen Sie uns einen Blick auf den Code werfen: | Lassen Sie uns einen Blick auf den Code werfen: | ||
<code> | <code> | ||
#include <QWidget> | |||
#include <QTextEdit> | |||
#include <QPushButton> | |||
class Notepad : public QWidget | class Notepad : public QWidget | ||
{ | { | ||
Line 117: | Line 123: | ||
private: | private: | ||
QTextEdit *textEdit; | QTextEdit *textEdit; | ||
QPushButton *quitButton; | QPushButton *quitButton; | ||
}; | }; | ||
</code> | </code> | ||
Das Q_OBJECT Makro | |||
Das Q_OBJECT Makro muss an erster Stelle einer Klassendefinition stehen; es deklariert unsere Klasse als [http://doc.qt.io/qt-4.8/qobject.html QObject] (natürlich muss sie auch vom QObject abgeleitet werden). Ein [http://doc.qt.io/qt-4.8/qobject.html QObject] reichert eine gewöhnlichen C++ Klasse mit einigen Fähigkeiten an. Beachtenswert ist die Möglichkeit den Klassen- und die Slotnamen zur Laufzeit abfragen zu können. Darüber hinaus ist es möglich die Parametertypen eines Slots abzufragen und den Slot aufzurufen. | |||
Zeile 13 deklariert den Slot quit(). Einfach durch das Benutzen des Slot Makros. Der quit() Slot kann nun mit den Signalen verbunden werden, die eine passende Signatur besitzen (Jedes Signal, das keine Argumente erwartet). | Zeile 13 deklariert den Slot quit(). Einfach durch das Benutzen des Slot Makros. Der quit() Slot kann nun mit den Signalen verbunden werden, die eine passende Signatur besitzen (Jedes Signal, das keine Argumente erwartet). | ||
Line 127: | Line 134: | ||
Anstatt in der main() Funktion die Benutzeroberfläche zu erstellen und den Slot zu verbinden, benutzen wir Notepads Konstruktor. | Anstatt in der main() Funktion die Benutzeroberfläche zu erstellen und den Slot zu verbinden, benutzen wir Notepads Konstruktor. | ||
<code> | <code> | ||
#include "notepad.h" | |||
#include <QApplication> | |||
Notepad::Notepad() | Notepad::Notepad() | ||
{ | { | ||
Line 134: | Line 144: | ||
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit())); | connect(quitButton, SIGNAL (clicked()), this, SLOT (quit())); | ||
QVBoxLayout | QVBoxLayout *layout = new QVBoxLayout; | ||
layout->addWidget(textEdit); | layout->addWidget(textEdit); | ||
layout->addWidget(quitButton); | layout->addWidget(quitButton); | ||
Line 143: | Line 153: | ||
} | } | ||
</code> | </code> | ||
Nun benutzen wir die | <code> | ||
void Notepad::quit() | |||
{ | |||
qApp->quit(); | |||
} | |||
</code> | |||
Wie Sie in der Klassendefinition sehen konnten, benutzen wir Zeiger unserer QObjects (textEdit und quitButton). In der Regel sollten Sie QObjects Objekte immer auf dem Heap erstellen und diese nie kopieren. | |||
Nun benutzen wir die [http://doc.qt.io/qt-4.8/qobject.html#tr tr()] Funktion um unsere sichtbaren Bezeichner. Diese Funktion ist notwendig falls Sie vorhaben Ihre Anwendung in mehreren Sprachen (z. B. Englisch und Chinesisch) bereit zu stellen. Wir werden hier jedoch nicht ins Detail gehen. Sie können dem Qt Linguist Link folgen um mehr darüber zu erfahren. | |||
=== Mehr erfahren === | |||
|''. Über |''. Hier | | |''. Über |''. Hier | | ||
| tr() und Internationalisierung | | | tr() und Internationalisierung | [http://doc.qt.io/qt-4.8/linguist-manual.html Qt Linguist Manual], [http://doc.qt.io/qt-4.8/i18n-source-translation.html Writing Source Code for Translation], [http://doc.qt.io/qt-4.8/linguist-hellotr.html Hello tr()] Example, [http://doc.qt.io/qt-4.8/internationalization.html Internationalization with Qt] | | ||
| | | [http://doc.qt.io/qt-4.8/qobject.html QObjects] und das Qt Object Model (Essenziell um Qt zu verstehen) | [http://doc.qt.io/qt-4.8/object.html Object Model] | | ||
| qmake und das Qt Erstellungssystem | | | qmake und das Qt Erstellungssystem | [http://doc.qt.io/qt-4.8/qmake-manual.html qmake Manual] | | ||
== Eine .pro Datei erstellen == | |||
In diesem Beispiel erstellen wir unsere eigene .pro Datei, anstatt uns eine durch | In diesem Beispiel erstellen wir unsere eigene .pro Datei, anstatt uns eine durch | ||
qmake -project Option generieren zu lassen. | qmake -project Option generieren zu lassen. | ||
Line 161: | Line 178: | ||
SOURCES = notepad.cpp main.cpp | SOURCES = notepad.cpp main.cpp | ||
</code> | </code> | ||
Die folgenden Kommandozeilen Kommandos erstellen die Beispielanwendung. | Die folgenden Kommandozeilen Kommandos erstellen die Beispielanwendung. | ||
<code> | <code> | ||
Line 166: | Line 184: | ||
make | make | ||
</code> | </code> | ||
Viele Anwendungen werden durch die Verwendung von | == Die Verwendung eines QMainWindow == | ||
Viele Anwendungen werden durch die Verwendung von [http://doc.qt.io/qt-4.8/qmainwindow.html QMainWindow] profitieren, das ihr eigenes Layout hat dem Sie eine Menüleiste, Dockwidgets, Werkzeugleisten und eine Statusleiste hinzufügen können. [http://doc.qt.io/qt-4.8/qmainwindow.html QMainWindow] besitzt einen zentralen Bereich, der durch beliebiges Widget besetzt werden kann. In unserem Fall werden wir unser Texteingabefeld dort platzieren. | |||
[[Image:http://doc.qt.io/qt-4.8/images/gs4.png|QMainWindow]] | |||
Lassen Sie uns einen Blick auf die neue Notepad Klassendefinition werfen: | Lassen Sie uns einen Blick auf die neue Notepad Klassendefinition werfen: | ||
<code> | <code> | ||
#include < | #include <QMainWindow> | ||
#include <QTextEdit> | |||
#include <QAction> | |||
#include <QMenu> | |||
class Notepad : public QMainWindow | class Notepad : public QMainWindow | ||
Line 195: | Line 216: | ||
QAction *exitAction; | QAction *exitAction; | ||
QMenu | QMenu *fileMenu; | ||
}; | }; | ||
</code> | </code> | ||
Wir fügen zwei weitere Slots hinzu, die ein Dokument speichern und schließen. Wir werden diese im nächsten Abschnitt implementieren. | Wir fügen zwei weitere Slots hinzu, die ein Dokument speichern und schließen. Wir werden diese im nächsten Abschnitt implementieren. | ||
In einem Hauptfenster soll der gleiche Slot oft mehrfach, durch verschiedene Widgets, aufgerufen werden können. Beispiele dafür sind Menüeinträge und Knöpfe in der Werkzeugleiste. Um dieses zu vereinfachen stellt Qt | In einem Hauptfenster soll der gleiche Slot oft mehrfach, durch verschiedene Widgets, aufgerufen werden können. Beispiele dafür sind Menüeinträge und Knöpfe in der Werkzeugleiste. Um dieses zu vereinfachen stellt Qt [http://doc.qt.io/qt-4.8/qaction.html QAction] bereit, die mehreren Widgets zugewiesen werden kann und mit einem Slot verbunden werden. Es können zum Beispiel sowohl [http://doc.qt.io/qt-4.8/qmenu.html QMenu] als auch [http://doc.qt.io/qt-4.8/qtoolbar.html QToolBar] Menüeinträge erzeugen unter Verwendung der gleichen [http://doc.qt.io/qt-4.8/qaction.html QActions]. Wir werden in Kürze sehen wie das funktioniert. | ||
Wie zuvor benutzen wir Notepads Konstruktur um die Benutzeroberfläche zu erstellen. | Wie zuvor benutzen wir Notepads Konstruktur um die Benutzeroberfläche zu erstellen. | ||
<code> | <code> | ||
#include "notepad.h" | |||
#include <QMenuBar> | |||
Notepad::Notepad() | Notepad::Notepad() | ||
{ | { | ||
openAction = new QAction(tr("& | openAction = new QAction(tr("&Open"), this); | ||
saveAction = new QAction(tr("& | saveAction = new QAction(tr("&Save"), this); | ||
exitAction = new QAction(tr("E& | exitAction = new QAction(tr("E&xit"), this); | ||
connect(openAction, SIGNAL (triggered()), this, SLOT (open())); | connect(openAction, SIGNAL (triggered()), this, SLOT (open())); | ||
connect(saveAction, SIGNAL (triggered()), this, SLOT (save())); | connect(saveAction, SIGNAL (triggered()), this, SLOT (save())); | ||
connect(exitAction, SIGNAL (triggered()), | connect(exitAction, SIGNAL (triggered()), this, SLOT (quit())); | ||
fileMenu = menuBar()->addMenu(tr("& | fileMenu = menuBar()->addMenu(tr("&File")); | ||
fileMenu->addAction(openAction); | fileMenu->addAction(openAction); | ||
fileMenu->addAction(saveAction); | fileMenu->addAction(saveAction); | ||
Line 226: | Line 251: | ||
} | } | ||
</code> | </code> | ||
[http://doc.qt.io/qt-4.8/qaction.html QActions] werden mit dem Text erstellt, der auf dem Widget erscheinen soll, dem wir es zuweisen (in unserem Fall Menüeinträge). Falls wir sie zusätzlich auch einer Werkzeugleiste zuweisen wollten, hätten wir den Aktionen auch ein [http://doc.qt.io/qt-4.8/qicon.html Icon] zuweisen können. | |||
Wenn nun ein Menüeintrag geklickt wird, löst der Eintrag die Aktion aus und der dazugehörige Slot wird aktiviert. | Wenn nun ein Menüeintrag geklickt wird, löst der Eintrag die Aktion aus und der dazugehörige Slot wird aktiviert. | ||
=== Mehr erfahren === | |||
|''. Über |''. Hier | | |''. Über |''. Hier | | ||
| Hauptanwendungsfenster und Hauptfensterklassen | | | Hauptanwendungsfenster und Hauptfensterklassen | [http://doc.qt.io/qt-4.8/mainwindow.html Application Main Window], [http://doc.qt.io/qt-4.8/examples-mainwindow.html Main Window Examples] | | ||
| MDI applications | | | MDI applications | [http://doc.qt.io/qt-4.8/qmdiarea.html QMdiArea], [http://doc.qt.io/qt-4.8/mainwindows-mdi.html MDI Example] | | ||
== Speichern und Laden == | |||
In diesem Beispiel werden wir die Funktionalität der open() und save() Slots implementieren, die wir im vorherigen Beispiel eingeführt haben. | In diesem Beispiel werden wir die Funktionalität der open() und save() Slots implementieren, die wir im vorherigen Beispiel eingeführt haben. | ||
[[Image:http://doc.qt.io/qt-4.8/images/gs5.png|Öffnen Dialog]] | |||
Wir werden mit dem open() Slot beginnen: | Wir werden mit dem open() Slot beginnen: | ||
<code> | <code> | ||
#include <QFileDialog> | |||
#include <QMessageBox> | |||
void Notepad::open() | |||
{ | |||
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", | QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", | ||
tr("Text Files ( | tr("Text Files (*.txt);;C++ Files (*.cpp *.h)")); | ||
if (fileName != "") { | if (fileName != "") { | ||
Line 256: | Line 285: | ||
textEdit->setPlainText(contents); | textEdit->setPlainText(contents); | ||
file.close(); | file.close(); | ||
} | |||
} | } | ||
</code> | </code> | ||
Sobald wir einen Dateinamen haben versuchen wir die Datei mittels | Der erste Schritt ist den Benutzer nach dem Dateinamen der Datei zu fragen, die er öffnen möchte. Qt stellt dafür ein [http://doc.qt.io/qt-4.8/qfiledialog.html QFileDialog] bereit, der einen Dialog darstellt in dem der Benutzer eine Datei auswählen kann. Das obere Bild zeigt den Dialog unter Kubuntu. Die statische [http://doc.qt.io/qt-4.8/qfiledialog.html#getOpenFileName getOpenFileName()] Funktion zeigt einen modalen Dateidialog bis der Benutzer eine Datei ausgewählt hat. Es liefert den Dateipfad der ausgesuchten Datei zurück oder eine leere Zeichenkette, falls der Dialog abgebrochen wurde. | ||
Sobald wir einen Dateinamen haben versuchen wir die Datei mittels [http://doc.qt.io/qt-4.8/qiodevice.html#open open()] zu öffnen. Die open() Funktion liefert true im Erfolgsfall. Wir werden hier nicht auf die Fehlerbehandlung eingehen, auf die mehr in den "Mehr erfahren" Verknüpfungen eingegangen wird. Im Fehlerfall benutzen wir [http://doc.qt.io/qt-4.8/qmessagebox.html QMessageBox] um einen Dialog mit einer Fehlermeldung anzuzeigen (siehe die [http://doc.qt.io/qt-4.8/qmessagebox.html QMessageBox] Klassen Beschreibung für weitere Details). | |||
Es ist recht einfach die Daten mit der Funktion | Es ist recht einfach die Daten mit der Funktion [http://doc.qt.io/qt-4.8/qiodevice.html#readAll readAll()] einzulesen, die alle Daten einer Datei in einem [http://doc.qt.io/qt-4.8/qbytearray.html QByteArray] zurück gibt. Die [http://doc.qt.io/qt-4.8/qbytearray.html#constData constData()] Funktion gibt alle Daten in einem const char''' Array zurück, zu dem [http://doc.qt.io/qt-4.8/qstring.html QString] einen Konstruktor bereit stellt. Der Inhalt kann danach im Texteingabefeld angezeigt werden. Danach schließen wir die Datei mittels [http://doc.qt.io/qt-4.8/qiodevice.html#close close()] Funktion, um den Dateidescriptor an das Betriebssystem zu übergeben. | ||
Lassen Sie uns nun zum save() Slot übergehen. | Lassen Sie uns nun zum save() Slot übergehen. | ||
<code> | <code> | ||
#include <QFileDialog> | |||
#include <QTextStream> | |||
void Notepad::save() | |||
{ | |||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", | QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", | ||
tr("Text Files ( | tr("Text Files (*.txt);;C++ Files (*.cpp *.h)")); | ||
if (fileName != "") { | if (fileName != "") { | ||
Line 274: | Line 310: | ||
// error message | // error message | ||
} else { | } else { | ||
QTextStream stream(& | QTextStream stream(&file); | ||
stream << textEdit->toPlainText(); | stream << textEdit->toPlainText(); | ||
stream.flush(); | stream.flush(); | ||
file.close(); | file.close(); | ||
} | } | ||
} | |||
} | |||
</code> | |||
Um den Inhalt des Texteingabefeldes zurück in die Datei zu schreiben verwenden wir die [http://doc.qt.io/qt-4.8/qtextstream.html QTextStream] Klasse, die das [http://doc.qt.io/qt-4.8/qfile.html QFile] Objekt umhüllt. Textstream kann QStrings direkt in eine Datei schreiben; [http://doc.qt.io/qt-4.8/qfile.html QFile] akzeptiert nur rohe Daten (char*) mit der [http://doc.qt.io/qt-4.8/qiodevice.html#write write()] Funktion des [http://doc.qt.io/qt-4.8/qiodevice.html QIODevice]. | |||
<code> | |||
#include <QApplication> | |||
#include <QMessageBox> | |||
void Notepad::quit() | |||
{ | |||
QMessageBox messageBox; | |||
messageBox.setWindowTitle(tr("Notepad")); | |||
messageBox.setText(tr("Do you really want to quit?")); | |||
messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); | |||
messageBox.setDefaultButton(QMessageBox::No); | |||
if (messageBox.exec() == QMessageBox::Yes) | |||
qApp->quit(); | |||
} | |||
</code> | |||
main.cpp | |||
<code> | |||
#include "notepad.h" | |||
#include <QApplication> | |||
int main(int argc, char *argv[]) | |||
{ | |||
QApplication app(argc, argv); | |||
Notepad notepad; | |||
notepad.show(); | |||
return app.exec(); | |||
} | } | ||
</code> | </code> | ||
=== Mehr erfahren | |||
=== Mehr erfahren === | |||
|''. Über |''. Hier | | |''. Über |''. Hier | | ||
| Dateien und E/A-Geräte | | | Dateien und E/A-Geräte | [http://doc.qt.io/qt-4.8/qfile.html QFile], [http://doc.qt.io/qt-4.8/qiodevice.html QIODevice] | === | ||
[[Category:Learning]] | [[Category:Learning]] | ||
[[Category:HowTo]] | [[Category:HowTo]] |
Latest revision as of 13:20, 7 June 2015
diese Seite in: en, es, ru, pl, pt, nl
Schnelleinstieg in die Programmierung mit Qt
Willkommen in der Welt von Qt des plattformübergreifenden GUI Framework. In dieser "Schnelleinstiegs"-anleitung lehren wir grundlegendes Qt Wissen durch das Implementieren einer einfachen Notepad Anwendung. Nach dem Durchlesen dieser Anleitung sind Sie soweit in die Übersichten und API Dokumentation einzutauchen und die Informationen zu finden, die Sie für die Anwendung brauchen, die Sie entwickeln.
Hallo Notepad
In diesem ersten Beispiel werden wir ein einfaches Texteingabefeld erstellen und in einem Fenster auf dem Desktop anzeigen. Das stellt das einfachste Qt Programm mit einer Benutzeroberfläche dar.
Hier ist der Code:
#include <QApplication>
#include <QTextEdit>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QTextEdit textEdit;
textEdit.show();
return app.exec();
}
Lassen Sie uns mal Zeile für Zeile durch den Code gehen. In den ersten beiden Zeilen binden wir die Headerdateien für QApplication und QTextEdit ein, die beide Klassen darstellen, die wir für dieses Beispiel benötigen. Alle Qt Klassen haben eine Headerdatei, die den Namen der Klasse trägt.
Zeile 6 erstellt ein QApplication Objekt. Dieses Objekt behandelt anwendungsweit Ressourcen und ist notwendig für eine Qt Anwendung mit einer grafischen Benutzeroberfläche. Der Konstruktor benötigt argc und argv, weil Qt ein Paar Kommandozeilenargumente entgegen nehmen kann.
Zeile 8 erstellt ein QTextEdit Objekt. Eine Texteingabefeld ist ein visuelles Element einer Benutzeroberfläche. In Qt nennen wir solche Elemente Widgets. Beispiele anderer Widgets sind Scrollbalken, Labels und Radiobuttons. Ein Widget kann auch ein Container für andere Widgets sein; ein Dialog oder ein Hauptanwendungsfenster zum Beispiel.
Zeile 9 zeigt das Texteingabefeld auf dem Bildschirm in seinem eigenen Fenster. Da Widgets auch als Container verwendet werden können (z.B. ein QMainWindow, das Toolbars, Menüs, Statuszeile und ein paar andere Widgets), ist es möglich ein einzelnes Widget in eigenem Fenster anzuzeigen. Widgets sind standardmäßig nicht sichtbar; die Funktion show() macht sie sichtbar.
Zeile 11 lässt QApplication in die Ereignisschleife eintreten. Solange eine Qt Anwendung läuft werden Ereignisse generiert und an die Widgets der Anwendung gesendet. Beispiele solcher Ereignisse sind Mausklicks oder Tastatureingaben. Wenn Sie einen Text in das Texteingabefeld eintippen empfängt es Tastatureingabe Ereignisse und beantwortet diese in dem es den eingegebenen Text darstellt.
Um die Anwendung auszuführen öffnen Sie die Kommandozeile und gehen zum Verzeichnis in dem Sie die .cpp Dateien des Programms liegen haben. Folgende Shell Kommandos übersetzen und erstellen das Programm.
qmake -project
qmake
make
Das wird eine ausführbare Datei im part1 Verzeichnis erstellen (unter Windows werden Sie u. U. nmake anstatt make verwenden müssen. Ferner wird die ausführbare Datei in part1/debug oder part1/release erstellt). qmake is Qts Erstellprogramm, das eine Konfigurationsdatei entgegen nimmt. qmake erstellt diese für uns, wenn das Argument -project übergeben wird. Mit der Konfigurationsdatei (mit der Endung .pro) erstellt qmake eine make Datei, das das Programm für Sie erstellt. Wir werden uns später ansehen wie man eigene .pro Datei schreibt.
Mehr erfahren
|. Über |. Hier | | Widgets und Fenstergeometrie | Window and Dialog Widgets | | Ereignisse und ihre Behandlung | The Event System |
Einen Beenden Knopf hinzufügen
In einer echten Anwendung werden Sie mehr als nur ein Widget benötigen. Wir werden nun einen QPushButton unter das Texteingabefeld anbringen. Der Knopf wird die Notepad Anwendung beim Betätigen (z. B. durch das Klicken mit der Maus) beenden.
Lassen Sie uns mal einen Blick auf den Code werfen:
#include <QApplication>
#include <QLayout>
#include <QTextEdit>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QTextEdit *textEdit = new QTextEdit;
QPushButton *quitButton = new QPushButton("&Quit");
QObject::connect(quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(textEdit);
layout->addWidget(quitButton);
QWidget window;
window.setLayout(&layout);
window.show();
return app.exec();
}
Zeile 13 verwendet Qts Signals and Slots Mechanismus um die Anwendung beim Drücken des Beenden Knopf zu schließen. Ein Slot ist eine Funktion, die durch die Verwendung ihres Namens (in Form einer Zeichenkette) zu Laufzeit aufgerufen werden kann. Ein Signal ist eine Funktion die, wenn aufgerufen, alle dazu registrierten Slots aufruft; wir nennen es einen Slot mit einem Signal verbinden und ein Signal erzeugen.
quit() ist ein Slot der QApplication, der die Anwendung beendet. clicked() ist ein Signal, das QPushButton erzeugt, wenn der Knopf gedrückt wird. Die statische QObject::connect() Funktion sorgt für die Verbindung des Slots und des Signals. SIGNAL () und SLOT() sind zwei Makros, die die Funktionssignatur des Signal bzw. Slot entgegennehmen, die verbunden werden sollen. Ferner müssen wir die Zeiger der Objekte übergeben, das das Signal sendet bzw. empfängt.
Zeile 15 erzeugt ein QVBoxLayout. Wie bereits erwähnt, können Widgets auch andere Widgets enthalten. Es ist möglich die Abgrenzungen (Größe und Position) eines Kindwidgets direkt zu setzen. Jedoch ist es einfacher ein Layout zu verwenden. Ein Layout verwaltet die Abgrenzungen der Kindwidgets. Beispielsweise positioniert QVBoxLayout die Kindelemente vertikal untereinander.
Zeile 16 und 17 fügen das Texteingabefeld und den Knopf dem Layout hinzu. In Zeile 20 setzen wir das Layout eines Widgets.
Mehr erfahren
|. Über |. Hier | | Signale und Slots | Signals & Slots | | Layouts | Layout Management, Widgets and Layouts, Layout Examples | | Widgets die Qt bereitstellt | Qt Widget Gallery, Widget Examples |
QWidget Unterklassen erstellen
Wenn der Benutzer die Anwendung beenden will ist es u. U. erwünscht einen Dialog anzuzeigen, der sicherstellt, dass der Benutzer die Anwendung tatsächlich beenden möchte. In diesem Beispiel erstellen wir eine QWidget Unterklasse und fügen einen Slot der Klasse hinzu, den wir mit dem Beenden Knopf verknüpfen.
Lassen Sie uns einen Blick auf den Code werfen:
#include <QWidget>
#include <QTextEdit>
#include <QPushButton>
class Notepad : public QWidget
{
Q_OBJECT
public:
Notepad();
private slots:
void quit();
private:
QTextEdit *textEdit;
QPushButton *quitButton;
};
Das Q_OBJECT Makro muss an erster Stelle einer Klassendefinition stehen; es deklariert unsere Klasse als QObject (natürlich muss sie auch vom QObject abgeleitet werden). Ein QObject reichert eine gewöhnlichen C++ Klasse mit einigen Fähigkeiten an. Beachtenswert ist die Möglichkeit den Klassen- und die Slotnamen zur Laufzeit abfragen zu können. Darüber hinaus ist es möglich die Parametertypen eines Slots abzufragen und den Slot aufzurufen.
Zeile 13 deklariert den Slot quit(). Einfach durch das Benutzen des Slot Makros. Der quit() Slot kann nun mit den Signalen verbunden werden, die eine passende Signatur besitzen (Jedes Signal, das keine Argumente erwartet).
Anstatt in der main() Funktion die Benutzeroberfläche zu erstellen und den Slot zu verbinden, benutzen wir Notepads Konstruktor.
#include "notepad.h"
#include <QApplication>
Notepad::Notepad()
{
textEdit = new QTextEdit;
quitButton = new QPushButton(tr("Quit"));
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(textEdit);
layout->addWidget(quitButton);
setLayout(layout);
setWindowTitle(tr("Notepad"));
}
void Notepad::quit()
{
qApp->quit();
}
Wie Sie in der Klassendefinition sehen konnten, benutzen wir Zeiger unserer QObjects (textEdit und quitButton). In der Regel sollten Sie QObjects Objekte immer auf dem Heap erstellen und diese nie kopieren.
Nun benutzen wir die tr() Funktion um unsere sichtbaren Bezeichner. Diese Funktion ist notwendig falls Sie vorhaben Ihre Anwendung in mehreren Sprachen (z. B. Englisch und Chinesisch) bereit zu stellen. Wir werden hier jedoch nicht ins Detail gehen. Sie können dem Qt Linguist Link folgen um mehr darüber zu erfahren.
Mehr erfahren
|. Über |. Hier | | tr() und Internationalisierung | Qt Linguist Manual, Writing Source Code for Translation, Hello tr() Example, Internationalization with Qt | | QObjects und das Qt Object Model (Essenziell um Qt zu verstehen) | Object Model | | qmake und das Qt Erstellungssystem | qmake Manual |
Eine .pro Datei erstellen
In diesem Beispiel erstellen wir unsere eigene .pro Datei, anstatt uns eine durch qmake -project Option generieren zu lassen.
HEADERS = notepad.h
SOURCES = notepad.cpp main.cpp
Die folgenden Kommandozeilen Kommandos erstellen die Beispielanwendung.
qmake
make
Die Verwendung eines QMainWindow
Viele Anwendungen werden durch die Verwendung von QMainWindow profitieren, das ihr eigenes Layout hat dem Sie eine Menüleiste, Dockwidgets, Werkzeugleisten und eine Statusleiste hinzufügen können. QMainWindow besitzt einen zentralen Bereich, der durch beliebiges Widget besetzt werden kann. In unserem Fall werden wir unser Texteingabefeld dort platzieren.
Lassen Sie uns einen Blick auf die neue Notepad Klassendefinition werfen:
#include <QMainWindow>
#include <QTextEdit>
#include <QAction>
#include <QMenu>
class Notepad : public QMainWindow
{
Q_OBJECT
public:
Notepad();
private slots:
void open();
void save();
void quit();
private:
QTextEdit *textEdit;
QAction *openAction;
QAction *saveAction;
QAction *exitAction;
QMenu *fileMenu;
};
Wir fügen zwei weitere Slots hinzu, die ein Dokument speichern und schließen. Wir werden diese im nächsten Abschnitt implementieren.
In einem Hauptfenster soll der gleiche Slot oft mehrfach, durch verschiedene Widgets, aufgerufen werden können. Beispiele dafür sind Menüeinträge und Knöpfe in der Werkzeugleiste. Um dieses zu vereinfachen stellt Qt QAction bereit, die mehreren Widgets zugewiesen werden kann und mit einem Slot verbunden werden. Es können zum Beispiel sowohl QMenu als auch QToolBar Menüeinträge erzeugen unter Verwendung der gleichen QActions. Wir werden in Kürze sehen wie das funktioniert.
Wie zuvor benutzen wir Notepads Konstruktur um die Benutzeroberfläche zu erstellen.
#include "notepad.h"
#include <QMenuBar>
Notepad::Notepad()
{
openAction = new QAction(tr("&Open"), this);
saveAction = new QAction(tr("&Save"), this);
exitAction = new QAction(tr("E&xit"), this);
connect(openAction, SIGNAL (triggered()), this, SLOT (open()));
connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));
connect(exitAction, SIGNAL (triggered()), this, SLOT (quit()));
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openAction);
fileMenu->addAction(saveAction);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);
textEdit = new QTextEdit;
setCentralWidget(textEdit);
setWindowTitle(tr("Notepad"));
}
QActions werden mit dem Text erstellt, der auf dem Widget erscheinen soll, dem wir es zuweisen (in unserem Fall Menüeinträge). Falls wir sie zusätzlich auch einer Werkzeugleiste zuweisen wollten, hätten wir den Aktionen auch ein Icon zuweisen können.
Wenn nun ein Menüeintrag geklickt wird, löst der Eintrag die Aktion aus und der dazugehörige Slot wird aktiviert.
Mehr erfahren
|. Über |. Hier | | Hauptanwendungsfenster und Hauptfensterklassen | Application Main Window, Main Window Examples | | MDI applications | QMdiArea, MDI Example |
Speichern und Laden
In diesem Beispiel werden wir die Funktionalität der open() und save() Slots implementieren, die wir im vorherigen Beispiel eingeführt haben.
Wir werden mit dem open() Slot beginnen:
#include <QFileDialog>
#include <QMessageBox>
void Notepad::open()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
tr("Text Files (*.txt);;C++ Files (*.cpp *.h)"));
if (fileName != "") {
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::critical(this, tr("Error"),
tr("Could not open file"));
return;
}
QString contents = file.readAll().constData();
textEdit->setPlainText(contents);
file.close();
}
}
Der erste Schritt ist den Benutzer nach dem Dateinamen der Datei zu fragen, die er öffnen möchte. Qt stellt dafür ein QFileDialog bereit, der einen Dialog darstellt in dem der Benutzer eine Datei auswählen kann. Das obere Bild zeigt den Dialog unter Kubuntu. Die statische getOpenFileName() Funktion zeigt einen modalen Dateidialog bis der Benutzer eine Datei ausgewählt hat. Es liefert den Dateipfad der ausgesuchten Datei zurück oder eine leere Zeichenkette, falls der Dialog abgebrochen wurde.
Sobald wir einen Dateinamen haben versuchen wir die Datei mittels open() zu öffnen. Die open() Funktion liefert true im Erfolgsfall. Wir werden hier nicht auf die Fehlerbehandlung eingehen, auf die mehr in den "Mehr erfahren" Verknüpfungen eingegangen wird. Im Fehlerfall benutzen wir QMessageBox um einen Dialog mit einer Fehlermeldung anzuzeigen (siehe die QMessageBox Klassen Beschreibung für weitere Details).
Es ist recht einfach die Daten mit der Funktion readAll() einzulesen, die alle Daten einer Datei in einem QByteArray zurück gibt. Die constData() Funktion gibt alle Daten in einem const char Array zurück, zu dem QString einen Konstruktor bereit stellt. Der Inhalt kann danach im Texteingabefeld angezeigt werden. Danach schließen wir die Datei mittels close() Funktion, um den Dateidescriptor an das Betriebssystem zu übergeben.
Lassen Sie uns nun zum save() Slot übergehen.
#include <QFileDialog>
#include <QTextStream>
void Notepad::save()
{
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "",
tr("Text Files (*.txt);;C++ Files (*.cpp *.h)"));
if (fileName != "") {
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
// error message
} else {
QTextStream stream(&file);
stream << textEdit->toPlainText();
stream.flush();
file.close();
}
}
}
Um den Inhalt des Texteingabefeldes zurück in die Datei zu schreiben verwenden wir die QTextStream Klasse, die das QFile Objekt umhüllt. Textstream kann QStrings direkt in eine Datei schreiben; QFile akzeptiert nur rohe Daten (char*) mit der write() Funktion des QIODevice.
#include <QApplication>
#include <QMessageBox>
void Notepad::quit()
{
QMessageBox messageBox;
messageBox.setWindowTitle(tr("Notepad"));
messageBox.setText(tr("Do you really want to quit?"));
messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
messageBox.setDefaultButton(QMessageBox::No);
if (messageBox.exec() == QMessageBox::Yes)
qApp->quit();
}
main.cpp
#include "notepad.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Notepad notepad;
notepad.show();
return app.exec();
}
Mehr erfahren
|. Über |. Hier | | Dateien und E/A-Geräte | QFile, QIODevice | ===