Kapitel 32. Dialogfenster

Sind Sie schon auf Dialoge gestoßen, die “richtig” aussehen, aber Benutzer irritieren?
Jeder Entwickler weiß, wie leicht man ein simples Einstellungsfenster in ein Labyrinth aus überflüssigen Buttons, seltsamer Modalität und unerwartet “hängender” Anwendung verwandeln kann.

Dieses Kapitel offenbart, warum ein Dialogfenster nicht “ein Formular mit Feldern” ist, sondern ein Schlüsselmechanismus zur Steuerung von Aufmerksamkeit und Workflow. Hier entdecken Sie einen praktischen Ansatz, den Entwickler verwenden: wie man es schafft, dass der Benutzer nicht über den Dialog nachdenkt — und dabei die Anwendung vorhersehbar, schnell und sauber bleibt.

Es werden 2 Modi (modal/nicht-modal) und deren Konsequenzen analysiert, Sie sehen funktionierende Patterns mit exec() und show(), sowie Techniken zur Verwaltung des Fenster-Lebenszyklus (einschließlich Qt::WA_DeleteOnClose). Plus — ein Set an Standard-Qt-Dialogen: QFileDialog, QFontDialog, QColorDialog, QInputDialog, QProgressDialog, QWizard und die “schwere Artillerie” QMessageBox.

Dieses Kapitel zu überspringen bedeutet, dem Benutzer sehr leicht Fenster zu “schenken”, die die Arbeit stören.

Das Kapitel enthält Code-Beispiele, die sofort einsatzbereit sind.

Selbstüberprüfung zum Kapitel

Warum ist bei modalen Dialogen eine statische Objekterstellung zulässig, während bei nicht-modalen Fenstern mit der Methode show() nur dynamische Erstellung empfohlen wird?Antwort
Richtige Antwort: Die Methode exec() blockiert die Code-Ausführung bis zum Schließen des Fensters, daher wird das statische Objekt nicht vorzeitig gelöscht. Die Methode show() gibt sofort die Kontrolle zurück, und bei statischer Erstellung wird das Objekt beim Verlassen des Scope zerstört, auch wenn das Fenster noch sichtbar sein sollte.
Warum sollte man für nicht-modale Fenster das Attribut Qt::WA_DeleteOnClose setzen, und was passiert ohne es?Antwort
Richtige Antwort: Das Attribut garantiert automatische Speicherfreigabe beim Schließen des Fensters durch den Benutzer. Ohne es bleibt ein dynamisch erstelltes nicht-modales Fenster nach dem Schließen im Speicher, was zu einem Memory Leak führt.
Warum sollten Menübefehle, die Dialoge öffnen, mit Auslassungspunkten enden (z.B. “Öffnen…”)?Antwort
Richtige Antwort: Auslassungspunkte dienen als visueller Hinweis für den Benutzer, dass das Klicken des Befehls die Aktion nicht sofort ausführt, sondern einen Dialog für zusätzliche Eingaben oder Bestätigung öffnet, was die Vorhersehbarkeit der Oberfläche verbessert.
Warum wird in der Schleife zur Verarbeitung langer Operationen mit QProgressDialog qApp->processEvents() aufgerufen?Antwort
Richtige Antwort: Der Aufruf von processEvents() erzwingt die Verarbeitung von GUI-Events vor jeder Iteration der Schleife, was dem Fortschrittsfenster ermöglicht, sich zu aktualisieren, auf Cancel-Button-Klicks zu reagieren und das “Einfrieren” der Oberfläche während langer Operationen verhindert.
Warum wird ein Dialog ohne Parent auf dem Bildschirm zentriert, während ein Dialog mit Parent relativ zum Parent-Widget zentriert wird?Antwort
Richtige Antwort: Die Zentrierung relativ zum Parent gewährleistet kontextuelle Nähe und logische Verbindung zwischen Hauptfenster und Dialog. Fenster ohne Parent werden auf dem Bildschirm als unabhängige UI-Elemente zentriert.
Warum ist scrollbarer Inhalt in Dialogen unerwünscht, und welche Lösung wird vorgeschlagen?Antwort
Richtige Antwort: Scrolling erschwert die Navigation und verschlechtert die Übersicht der Steuerelemente. Stattdessen wird empfohlen, Elemente logisch zu gruppieren und mit Tabs (QTabWidget) anzuordnen, sodass der Benutzer alle Inhalte ohne Scrolling sehen kann.
In welchen Situationen ist ein modaler Dialog einem nicht-modalen vorzuziehen?Antwort
Richtige Antwort: Modale Fenster sind vorzuziehen, wenn die Anwendung ohne Benutzerentscheidung nicht fortfahren kann — z.B. bei kritischen Fehlern, der Notwendigkeit zum Speichern von Daten vor dem Schließen oder der Auswahl obligatorischer Operationsparameter.
Wie signalisiert die Methode QColorDialog::getColor(), dass der Benutzer Cancel gedrückt hat, und warum wurde dieser Ansatz gewählt?Antwort
Richtige Antwort: Die Methode gibt ein QColor-Objekt zurück, und für dieses Objekt wird isValid() aufgerufen — wenn es false zurückgibt, wurde Cancel gedrückt. Dieser Ansatz ermöglicht es, sowohl die gewählte Farbe als auch den Operationsstatus über ein zurückgegebenes Objekt zu liefern.
Was passiert, wenn in einem modalen Fenster die clicked()-Signale der Ok- und Cancel-Buttons nicht mit den Slots accept() und reject() verbunden werden?Antwort
Richtige Antwort: Die Methode exec() kann keine korrekten Werte QDialog::Accepted oder QDialog::Rejected beim Klicken der Buttons zurückgeben, was die Bestimmung der Benutzerauswahl im aufrufenden Code unmöglich macht.
Warum sollte man der Methode QProgressDialog::setMinimumDuration() den Wert 0 übergeben, und wie beeinflusst dies das Verhalten?Antwort
Richtige Antwort: Der Wert 0 gibt an, dass das Fortschrittsfenster sofort ohne Verzögerung angezeigt werden soll. Standardmäßig wird das Fenster nur angezeigt, wenn die Operation länger als 3 Sekunden dauert — dies verhindert das Flackern des Fensters bei schnellen Operationen.
Was gibt QFileDialog::getSaveFileName() zurück, wenn der Benutzer Cancel drückt, und wie prüft man das?Antwort
Richtige Antwort: Die Methode gibt einen leeren QString zurück. Man kann dies mit isEmpty() prüfen — wenn es true zurückgibt, hat der Benutzer die Dateiauswahl abgebrochen, und die Speicheroperation sollte nicht ausgeführt werden.
Warum sollte man in Message-Boxen mit mehreren Buttons immer einen Cancel-Button definieren und setEscapeButton() setzen?Antwort
Richtige Antwort: Benutzer drücken häufig die Esc-Taste zum Abbrechen einer Aktion, und ohne setEscapeButton() kann ein solcher Tastendruck zu unvorhersehbarem Verhalten oder der Auswahl eines unerwarteten Buttons führen, was die User Experience verschlechtert.
Warum wird empfohlen, nach dem Aufruf von show() für nicht-modale Fenster raise() und activateWindow() aufzurufen?Antwort
Richtige Antwort: Diese Methoden garantieren, dass das nicht-modale Fenster über dem Hauptfenster der Anwendung sichtbar ist und den Eingabefocus erhält, was das Problem des versteckten Fensters löst, das auf einigen Plattformen auftreten kann.

Praktische Aufgaben

Einfaches Niveau

Benutzerdaten-Eingabedialog
Erstellen Sie einen modalen Dialog zur Eingabe von Benutzerinformationen: Name, Alter und E-Mail. Nach dem Schließen des Fensters per OK-Button soll das Hauptfenster die eingegebenen Daten in einer QMessageBox anzeigen. Bei Cancel sollen die Daten nicht angezeigt werden.
Hinweise: Erben Sie die Klasse von QDialog. Verwenden Sie QLineEdit für Textfelder und QSpinBox für das Alter. Verbinden Sie die OK- und Cancel-Buttons mit den Slots accept() und reject(). Erstellen Sie Getter-Methoden zum Abrufen der eingegebenen Daten. Prüfen Sie das Ergebnis von exec() im Hauptfenster.

Mittleres Niveau

Nicht-modales Einstellungsfenster mit Speicherung
Erstellen Sie ein nicht-modales Einstellungsfenster mit Tabs: “Allgemein”, “Oberfläche” und “Erweitert”. Jeder Tab soll mehrere Checkboxen und Comboboxen enthalten. Implementieren Sie Buttons “Übernehmen”, “OK” und “Schließen”. Das Fenster soll sich seine Position merken und beim erneuten Öffnen an derselben Stelle erscheinen. Verwenden Sie hide() statt des Schließens des Fensters und Qt::WA_DeleteOnClose für korrekte Speicherverwaltung.
Hinweise: Verwenden Sie QTabWidget für Tabs. Zum Speichern der Position überschreiben Sie closeEvent() und rufen hide() auf. Speichern Sie den Pointer zum Einstellungsfenster in der Hauptklasse. Der “Übernehmen”-Button soll Änderungen signalisieren, ohne das Fenster zu schließen. Verwenden Sie QSettings zum Speichern von Einstellungen zwischen Starts.

Schwieriges Niveau

Projekterstellungs-Wizard mit Validierung
Implementieren Sie einen Dialog-Wizard (QWizard) zur Erstellung eines neuen Projekts mit vier Seiten: Projekttyp-Auswahl, Angabe von Name und Pfad, Build-Parameter-Konfiguration und finale Bestätigungsseite. Fügen Sie Validierung auf jeder Seite hinzu: der “Weiter”-Button soll deaktiviert sein, bis der Benutzer alle Pflichtfelder ausgefüllt hat. Implementieren Sie Seitenübergänge unter Berücksichtigung vorheriger Auswahlen (z.B. bei Auswahl von “Konsolenanwendung” die GUI-Einstellungsseite überspringen). Nach Abschluss des Wizards erstellen Sie eine Datei mit Projekteinstellungen und zeigen QProgressDialog beim “Erstellen” der Projektstruktur an.
Hinweise: Verwenden Sie QWizardPage mit Überschreiben der Methoden validatePage() und isComplete(). Für bedingte Übergänge verwenden Sie setField() und field() zum Datenaustausch zwischen Seiten oder überschreiben Sie nextId(). Zur dynamischen Aktivierung des “Weiter”-Buttons verbinden Sie textChanged()- oder currentIndexChanged()-Signale mit dem completeChanged()-Slot. Auf der finalen Seite rufen Sie QFileDialog::getSaveFileName() zur Auswahl des Speicherorts der Konfiguration auf.

💬 Beteiligen Sie sich an der Diskussion!

Haben Sie modale und nicht-modale Fenster gemeistert? Haben Sie Fragen dazu, wann QDialog::exec() und wann show() zu verwenden ist?

Teilen Sie Ihre Erfahrungen mit Dialogfenstern, berichten Sie über ungewöhnliche Anwendungsfälle von QWizard oder QProgressDialog, oder helfen Sie anderen Lesern, die Feinheiten der Speicherverwaltung bei dynamischer Fenstererstellung zu verstehen!

Diskutieren wir: Welche Dialog-Design-Regeln halten Sie für am wichtigsten? Sind Sie auf Fälle gestoßen, in denen Standard-Qt-Dialoge nicht passten und Sie eigene Lösungen erstellen mussten?

Leave a Reply

Your email address will not be published. Required fields are marked *