====== Dialoge selbst erstellen ====== Im vorherigen Kapitel haben wir gesehen wie wir vordefinierte Dialoge verwenden können. Diese Dialoge werden häufig benötigt und sind deshalb sehr praktisch. Trotzdem werden wir in den meisten Fällen einen benutzerdefinierten Dialog benötigen. Im folgenden beschränken wir uns darauf, dass ein Objekt von unserem Dialog angelegt werden muss und die eingegeben Daten über eine Methode abgefragt werden müssen. \\ Nun wollen wir Schritt für Schritt einen eigenen Dialog implementieren. ===== Einzugebende Daten festlegen ===== Dieser Schritt ist von einem Anwendungsfall zum andern verschieden. In jedem Fall ist es empfehlenswert sich eine eigene Klasse für diese Daten anzulegen. In unserem Beispiel wollen wir Informationen über eine Person abfragen. Dabei beschränken wir uns auf Vorname, Nachname, Alter und Geschlecht. Die Klasse für unsere Daten würde entsprechend so aussehen: #include class Person { public: Person( const QString& firstName, const QString& lastName, const unsigned char age, const bool gender ) : m_firstName( firstName ), m_lastName( lastName ), m_age( age ), m_gender( gender ) { } const QString& firstName() { return m_firstName; } const QString& lastName() { return m_lastName; } unsigned char age() { return m_age; } bool gender() { return m_gender; } static const bool Male = true; static const bool Female = false; private: QString m_firstName, m_lastName; unsigned char m_age; bool m_gender; }; Diese Implementierung enthält natürlich nur jene für die Demonstration notwendige Funktionalität. ===== Design der Eingabemaske ===== Wir wollen unseren Dialog relativ schlicht halten. Deshalb verwenden wir 2 ''QLineEdit''-Widgets für die beiden Namen, eine ''QSpinBox'' fürs Alter und eine ''QComboBox'' für das Geschlecht. Damit der Benutzer weiß welche Daten eingegeben werden sollen, wollen wir eine kurze Beschreibung vor dem jeweiligen Eingabefeld. Dafür eignet sich am besten ein [[frameworks:qt:gui:basic:layouts#formularlayout|Formular-Layout]]. \\ Das wars zu unseren Daten. Was natürlich noch fehlt ist ein Button zum Bestätigen der Eingabe, den wir mit einem ''QVBoxLayout'' mit dem Formular verbinden und auf unseren Dialog anwenden. ===== Implementierung des Dialogs ===== Wir könnten unseren Dialog natürlich auch basiert auf ''QWidget'' erstellen, jedoch nimmt uns ''QDialog'' einiges an Arbeit ab. class PersonDialog : public QDialog \\ Wie wir wissen ist ein Dialog mit einem Parent-Objekt automatisch an oberster Stelle und zentriert über dem Eltern-Widget angezeig. Dieses Verhalten übernehmen wir einfach von ''QDialog'' und bieten einen entsprechenden Konstruktor mit einem optionalen ''QWidget'' als Parameter an. Der Rest des Konstruktors legt die weiteren Eigenschaften der einzelnen Widgets fest und platziert sie in einem Layout.\\ Hervorzuheben ist noch die Verbindung zwischen ''m_confirmButton.clicked()'' und ''accept()'' des Dialogs. Der Slot ''accept()'' erledigt gleich mehrere Schritte in einem. Der ausgeführte Dialog wird versteckt und das Ergebnis des Dialogs auf ''QDialog::Accepted''. Das bedeutet, dass gültige Daten eingegeben wurden. Wir könnten auch noch eine Prüfung einfügen, ob überhaupt ein Vorname und ein Nachname eingegeben wurden und im Fehlerfall ''reject()'' aufrufen. Der Einfachheit wegen verzichten wir in diesem Beispiel darauf. Falls der Dialog modal war, wird die Ausführung des restlichen Programms nach dem Aufruf einer der beiden Funktionen fortgesetzt. PersonDialog::PersonDialog( QWidget *parent ) : QDialog( parent ), m_firstName( new QLineEdit() ), m_lastName( new QLineEdit() ), m_age( new QSpinBox() ), m_gender( new QComboBox() ), m_confirmButton( new QPushButton( "Confirm" ) ) { m_age->setRange( 0, 150 ); m_gender->addItem( "Male" ); m_gender->addItem( "Female" ); connect( m_confirmButton, SIGNAL( clicked() ), this, SLOT( accept() ) ); QVBoxLayout *vLayout = new QVBoxLayout( this ); QFormLayout *fLayout = new QFormLayout(); fLayout->addRow( "First Name:", m_firstName ); fLayout->addRow( "Last Name:", m_lastName ); fLayout->addRow( "Age:", m_age ); fLayout->addRow( "Gender:", m_gender ); vLayout->addLayout( fLayout ); QHBoxLayout *hLayout = new QHBoxLayout(); hLayout->addStretch(); hLayout->addWidget( m_confirmButton ); vLayout->addLayout( hLayout ); } \\ Die einzige Methode die wir noch brauchen ist für die Abfrage der eingegebenen Daten. Sie übernimmt einfach die in die Widgets eingegeben Daten und schreibt sie in unser ''Person''-Objekt, das dann zurückgegeben wird. Person PersonDialog::getPerson() const { return Person( m_firstName->text(), m_lastName->text(), m_age->value(), m_gender->itemText( m_gender->currentIndex() ) == "Male" ? Person::Male : Person::Female ); } ===== Verwendung des Dialogs ===== Die Verwendung des Dialogs ist recht intuitiv und sollte klar sein: PersonDialog dialog; dialog.exec(); Person p = dialog.getPerson(); ===== Gesamter Beispielcode, Screenshot und Ausgabe ===== Zusammenfassend noch der gesamte Code des Beispiels: // main.cpp #include #include #include "PersonDialog.h" #include "Person.h" int main( int argc, char *argv[] ) { QApplication app( argc, argv ); PersonDialog dialog; dialog.exec(); Person p = dialog.getPerson(); qDebug() << p.firstName() << p.lastName() << p.age() << ( p.gender() == Person::Male ? "Male" : "Female" ); return 0; } // Person.h #ifndef PERSON_H #define PERSON_H #include class Person { public: Person( const QString& firstName, const QString& lastName, const unsigned char age, const bool gender ) : m_firstName( firstName ), m_lastName( lastName ), m_age( age ), m_gender( gender ) { } const QString& firstName() { return m_firstName; } const QString& lastName() { return m_lastName; } unsigned char age() { return m_age; } bool gender() { return m_gender; } static const bool Male = true; static const bool Female = false; private: QString m_firstName, m_lastName; unsigned char m_age; bool m_gender; }; #endif // PERSON_H // PersonDialog.h #ifndef PERSONDIALOG_H #define PERSONDIALOG_H #include class Person; class QLineEdit; class QSpinBox; class QComboBox; class QPushButton; class PersonDialog : public QDialog { public: PersonDialog( QWidget *parent = NULL ); Person getPerson() const; private: QLineEdit *m_firstName, *m_lastName; QSpinBox *m_age; QComboBox *m_gender; QPushButton *m_confirmButton; }; #endif // PERSONDIALOG_H // PersonDialog.cpp #include "PersonDialog.h" #include "Person.h" #include #include #include #include #include #include #include PersonDialog::PersonDialog( QWidget *parent ) : QDialog( parent ), m_firstName( new QLineEdit() ), m_lastName( new QLineEdit() ), m_age( new QSpinBox() ), m_gender( new QComboBox() ), m_confirmButton( new QPushButton( "Confirm" ) ) { m_age->setRange( 0, 150 ); m_gender->addItem( "Male" ); m_gender->addItem( "Female" ); connect( m_confirmButton, SIGNAL( clicked() ), this, SLOT( accept() ) ); QVBoxLayout *vLayout = new QVBoxLayout( this ); QFormLayout *fLayout = new QFormLayout(); fLayout->addRow( "First Name:", m_firstName ); fLayout->addRow( "Last Name:", m_lastName ); fLayout->addRow( "Age:", m_age ); fLayout->addRow( "Gender:", m_gender ); vLayout->addLayout( fLayout ); QHBoxLayout *hLayout = new QHBoxLayout(); hLayout->addStretch(); hLayout->addWidget( m_confirmButton ); vLayout->addLayout( hLayout ); } Person PersonDialog::getPerson() const { return Person( m_firstName->text(), m_lastName->text(), m_age->value(), m_gender->itemText( m_gender->currentIndex() ) == "Male" ? Person::Male : Person::Female ); } \\ Nun bekommen wir folgenden Dialog angezeigt: \\ {{:frameworks:qt:gui:basic:persondialog.png?|}} \\ Ein Klick auf den Button liefert diese Ausgabe: "Max" "Mustermann" 18 Male