Beispiel für einen Lizenz-Assistenten
Das Beispiel „Lizenz-Assistent“ zeigt, wie man komplexe Assistenten in Qt implementiert.

Die meisten Assistenten haben eine lineare Struktur, bei der auf Seite 1 Seite 2 folgt und so weiter bis zur letzten Seite. Das Beispiel „Trivial Wizard“ zeigt, wie man solche Assistenten erstellt.
Manche Assistenten sind komplexer, da sie je nach den vom Benutzer eingegebenen Informationen unterschiedliche Abläufe ermöglichen. Das Beispiel „Lizenz-Assistent“ veranschaulicht dies. Es bietet mehrere Assistentenseiten; je nachdem, welche Optionen ausgewählt werden, gelangt der Benutzer zu unterschiedlichen Seiten.

Das Beispiel besteht aus den folgenden Klassen:
LicenseWizarderbt von ` QWizard ` und implementiert einen nichtlinearen Assistenten mit fünf Seiten, der den Benutzer durch den Prozess der Auswahl einer Lizenzvereinbarung führt.IntroPage, „EvaluatePage“, „RegisterPage“, „DetailsPage“ und „ConclusionPage“ sind Unterklassen von „ QWizardPage “, die die Assistentenseiten implementieren.
Die Klasse „LicenseWizard“
Die Klasse „ LicenseWizard “ leitet sich von „ QWizard “ ab und stellt einen fünfseitigen Assistenten bereit, der den Benutzer durch den Registrierungsprozess seiner Kopie eines fiktiven Softwareprodukts führt. Hier ist die Klassendefinition:
class LicenseWizard : public QWizard
{
Q_OBJECT
public:
enum { Page_Intro, Page_Evaluate, Page_Register, Page_Details,
Page_Conclusion };
LicenseWizard(QWidget *parent = nullptr);
private slots:
void showHelp();
};Die öffentliche API der Klasse beschränkt sich auf einen Konstruktor und eine Enumeration. Die Enumeration definiert die IDs, die den verschiedenen Seiten zugeordnet sind:
| Klassenname | Enum-Wert | Seiten-ID |
|---|---|---|
IntroPage | Page_Intro | 0 |
EvaluatePage | Page_Evaluate | 1 |
RegisterPage | Page_Register | 2 |
DetailsPage | Page_Details | 3 |
ConclusionPage | Page_Conclusion | 4 |
In diesem Beispiel sind die IDs beliebig gewählt. Die einzigen Einschränkungen bestehen darin, dass sie eindeutig sein müssen und sich von -1 unterscheiden müssen. Mithilfe von IDs können wir auf Seiten verweisen.
LicenseWizard::LicenseWizard(QWidget *parent)
: QWizard(parent)
{
setPage(Page_Intro, new IntroPage);
setPage(Page_Evaluate, new EvaluatePage);
setPage(Page_Register, new RegisterPage);
setPage(Page_Details, new DetailsPage);
setPage(Page_Conclusion, new ConclusionPage);
setStartId(Page_Intro);Im Konstruktor erstellen wir die fünf Seiten, fügen sie mit ` QWizard::setPage()` in den Assistenten ein und legen ` Page_Intro ` als erste Seite fest.
#ifndef Q_OS_MACOS
setWizardStyle(ModernStyle);
#endifWir legen den Stil für „ ModernStyle “ auf allen Plattformen außer macOS fest,
setOption(HaveHelpButton, true);
setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo.png"));
connect(this, &QWizard::helpRequested, this, &LicenseWizard::showHelp);
setWindowTitle(tr("License Wizard"));
}Wir konfigurieren „ QWizard “ so, dass eine Schaltfläche „ Help “ angezeigt wird, die mit unserem Slot „ showHelp() “ verbunden ist. Außerdem legen wir die „ LogoPixmap “ für alle Seiten fest, die eine Kopfzeile haben (d. h. EvaluatePage, RegisterPage und DetailsPage).
void LicenseWizard::showHelp()
{
static QString lastHelpMessage;
QString message;
switch (currentId()) {
case Page_Intro:
message = tr("The decision you make here will affect which page you "
"get to see next.");
break;
...
default:
message = tr("This help is likely not to be of any help.");
}
if (lastHelpMessage == message)
message = tr("Sorry, I already gave what help I could. "
"Maybe you should try asking a human?");
QMessageBox::information(this, tr("License Wizard Help"), message);
lastHelpMessage = message;
}In „ showHelp() “ zeigen wir Hilfstexte an, die zur aktuellen Seite passen. Wenn der Nutzer auf derselben Seite zweimal auf „ Help “ klickt, sagen wir: „Tut mir leid, ich habe bereits alle Hilfe gegeben, die ich geben konnte. Vielleicht solltest du es mal bei einem Menschen versuchen?“
Die Klasse „IntroPage“
Die Seiten werden in „ licensewizard.h “ definiert und in „ licensewizard.cpp “ zusammen mit „ LicenseWizard “ implementiert.
Hier sind die Definition und die Implementierung von ` IntroPage`:
class IntroPage : public QWizardPage
{
Q_OBJECT
public:
IntroPage(QWidget *parent = nullptr);
int nextId() const override;
private:
QLabel *topLabel;
QRadioButton *registerRadioButton;
QRadioButton *evaluateRadioButton;
};
IntroPage::IntroPage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Introduction"));
setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark.png"));
topLabel = new QLabel(tr("This wizard will help you register your copy of "
"<i>Super Product One</i>™ or start "
"evaluating the product."));
topLabel->setWordWrap(true);
registerRadioButton = new QRadioButton(tr("&Register your copy"));
evaluateRadioButton = new QRadioButton(tr("&Evaluate the product for 30 "
"days"));
registerRadioButton->setChecked(true);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(topLabel);
layout->addWidget(registerRadioButton);
layout->addWidget(evaluateRadioButton);
setLayout(layout);
}Eine Seite erbt von ` QWizardPage`. Wir legen eine ` title ` und eine ` watermark pixmap` fest. Indem wir keine ` subTitle` festlegen, stellen wir sicher, dass für diese Seite keine Kopfzeile angezeigt wird. (Unter Windows ist es üblich, dass Assistenten auf der ersten und letzten Seite ein Wasserzeichen-Pixmap anzeigen und auf den anderen Seiten eine Kopfzeile haben.)
int IntroPage::nextId() const
{
if (evaluateRadioButton->isChecked()) {
return LicenseWizard::Page_Evaluate;
} else {
return LicenseWizard::Page_Register;
}
}Die Funktion „ nextId() “ gibt die ID für „ EvaluatePage “ zurück, wenn die Option „ Evaluate the product for 30 days “ aktiviert ist; andernfalls gibt sie die ID für „ RegisterPage “ zurück.
Die Klasse „EvaluatePage“
Die „ EvaluatePage “-Funktion ist etwas komplexer:
class EvaluatePage : public QWizardPage
{
Q_OBJECT
public:
EvaluatePage(QWidget *parent = nullptr);
int nextId() const override;
private:
QLabel *nameLabel;
QLabel *emailLabel;
QLineEdit *nameLineEdit;
QLineEdit *emailLineEdit;
};
EvaluatePage::EvaluatePage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Evaluate <i>Super Product One</i>™"));
setSubTitle(tr("Please fill both fields. Make sure to provide a valid "
"email address (e.g., john.smith@example.com)."));
nameLabel = new QLabel(tr("N&ame:"));
nameLineEdit = new QLineEdit;
...
registerField("evaluate.name*", nameLineEdit);
registerField("evaluate.email*", emailLineEdit);
...
}Zunächst legen wir die „ title “ und „ subTitle “ der Seite fest.
Anschließend erstellen wir die untergeordneten Widgets, legen die zugehörigen „ wizard fields “ an und fügen sie in Layouts ein. Die Felder werden mit einem Sternchen (*) neben ihrem Namen erstellt. Dadurch werden sie zu „ mandatory fields “, d. h. zu Feldern, die ausgefüllt werden müssen, bevor der Benutzer auf die Schaltfläche „ Next “ (Continue unter macOS) klicken kann. Auf die Werte der Felder kann von jeder anderen Seite aus über ` QWizardPage::field()` zugegriffen werden.
Das Zurücksetzen der Seite führt dazu, dass die beiden Textfelder geleert werden.
int EvaluatePage::nextId() const
{
return LicenseWizard::Page_Conclusion;
}Die nächste Seite ist immer „ ConclusionPage “.
Die Klasse „ConclusionPage“
Die Methoden „ RegisterPage “ und „ DetailsPage “ sind denen von „ EvaluatePage “ sehr ähnlich. Kommen wir direkt zur Methode „ ConclusionPage “:
class ConclusionPage : public QWizardPage
{
Q_OBJECT
public:
ConclusionPage(QWidget *parent = nullptr);
void initializePage() override;
int nextId() const override;
void setVisible(bool visible) override;
private slots:
void printButtonClicked();
private:
QLabel *bottomLabel;
QCheckBox *agreeCheckBox;
};Dieses Mal implementieren wir zusätzlich zu ` nextId()` auch ` QWizardPage::initializePage()` und ` QWidget::setVisible()` neu. Außerdem deklarieren wir einen privaten Slot: ` printButtonClicked()`.
int IntroPage::nextId() const
{
if (evaluateRadioButton->isChecked()) {
return LicenseWizard::Page_Evaluate;
} else {
return LicenseWizard::Page_Register;
}
}Die Standardimplementierung von ` QWizardPage::nextId()` gibt die Seite mit der nächsthöheren ID zurück oder -1, wenn die aktuelle Seite die höchste ID hat. Dieses Verhalten würde hier funktionieren, da ` Page_Conclusion ` gleich 5 ist und es keine Seite mit einer höheren ID gibt. Um jedoch nicht auf ein solch subtiles Verhalten angewiesen zu sein, implementieren wir ` nextId()` neu, sodass es -1 zurückgibt.
void ConclusionPage::initializePage()
{
QString licenseText;
if (wizard()->hasVisitedPage(LicenseWizard::Page_Evaluate)) {
licenseText = tr("<u>Evaluation License Agreement:</u> "
"You can use this software for 30 days and make one "
"backup, but you are not allowed to distribute it.");
} else if (wizard()->hasVisitedPage(LicenseWizard::Page_Details)) {
const QString emailAddress = field("details.email").toString();
licenseText = tr("<u>First-Time License Agreement:</u> "
"You can use this software subject to the license "
"you will receive by email sent to %1.").arg(emailAddress);
} else {
licenseText = tr("<u>Upgrade License Agreement:</u> "
"This software is licensed under the terms of your "
"current license.");
}
bottomLabel->setText(licenseText);
}Wir verwenden QWizard::hasVisitedPage(), um den Typ der vom Benutzer ausgewählten Lizenzvereinbarung zu ermitteln. Wenn der Benutzer das Feld „ EvaluatePage “ ausgefüllt hat, bezieht sich der Lizenztext auf eine Evaluierungslizenzvereinbarung. Wenn der Benutzer das Feld „ DetailsPage “ ausgefüllt hat, handelt es sich bei dem Lizenztext um eine Erstlizenzvereinbarung. Wenn der Benutzer einen Upgrade-Schlüssel angegeben und das Feld „ DetailsPage “ übersprungen hat, handelt es sich bei dem Lizenztext um eine Update-Lizenzvereinbarung.
void ConclusionPage::setVisible(bool visible)
{
QWizardPage::setVisible(visible);
if (visible) {
wizard()->setButtonText(QWizard::CustomButton1, tr("&Print"));
wizard()->setOption(QWizard::HaveCustomButton1, true);
connect(wizard(), &QWizard::customButtonClicked,
this, &ConclusionPage::printButtonClicked);
} else {
wizard()->setOption(QWizard::HaveCustomButton1, false);
disconnect(wizard(), &QWizard::customButtonClicked,
this, &ConclusionPage::printButtonClicked);
}
}Wir möchten im Assistenten die Schaltfläche „ Print “ anzeigen, wenn die Seite „ ConclusionPage “ angezeigt wird. Eine Möglichkeit, dies zu erreichen, besteht darin, die Funktion „ QWidget::setVisible()“ neu zu implementieren:
- Wenn die Seite angezeigt wird, setzen wir den Text der Schaltfläche „ CustomButton1 “ auf Print, aktivieren die Option „ HaveCustomButton1 “ und verbinden das Signal „ customButtonClicked()“ des „ QWizard “ mit unserem Slot „
printButtonClicked()“. - Ist die Seite ausgeblendet, deaktivieren wir die Option „ HaveCustomButton1 “ und trennen die Verbindung zum Slot „
printButtonClicked()“.
Siehe auch „ QWizard “ und „Trivial Wizard Example“.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.