Jeder Entwickler kennt das: Die Benutzeroberfläche funktioniert zwar scheinbar, aber die Benutzer sind verwirrt, klicken „an die falsche Stelle” und machen Fehler. Es gibt eine Auswahl – aber sie ist so implementiert, dass sie zur Problemquelle wird statt zur Erleichterung.
Dieses Kapitel enthüllt, warum Auswahlelemente einer der tückischsten Bereiche der GUI sind. Sie werden entdecken, wie einfache Listen, Tabellen und Tabs entweder die Arbeit des Benutzers beschleunigen oder unmerklich die UX und Performance der Anwendung zerstören können.
Es wird gezeigt, wie sich in der Praxis QListWidget, QTreeWidget und QTableWidget unterscheiden, wann der Icon-Modus zur Falle wird und warum das Hinzufügen von Widgets innerhalb von Elementen die Anwendung um ein Vielfaches verlangsamen kann. Außerdem werden Signale, Sortierung, Drag & Drop und die Feinheiten der Bearbeitung behandelt – gerade so viel, um das System als Ganzes zu verstehen.
Dieses Kapitel zu überspringen bedeutet, später für architektonische Entscheidungen zu bezahlen, die „nach Gefühl” getroffen wurden.
Das Kapitel enthält Code-Beispiele, die sofort einsatzbereit sind.
Selbsttest zum Kapitel
Warum reduziert die Verwendung von Widgets in Listenelementen (QListWidget, QTreeWidget) die Performance erheblich?Antwort
Richtige Antwort: Jedes Widget erfordert eigenes Rendering, Event-Handling und Ressourcenverwaltung. Bei Hunderten von Elementen erzeugt dies eine erhebliche Last, daher wird empfohlen, Views zu verwenden (z.B. checkState für Checkboxen) statt echter Widgets.
Was ist der Hauptvorteil der Model-View-Architektur gegenüber den Klassen QListWidget, QTreeWidget und QTableWidget?Antwort
Richtige Antwort: Die Model-View-Architektur trennt Daten und ihre Darstellung, was mehr Flexibilität bietet, die Möglichkeit, dieselben Daten in mehreren Views zu verwenden, und bessere Performance bei der Arbeit mit großen Datenmengen ermöglicht.
Welche Kombination von Flags benötigt ein Listenelement, damit der Benutzer es auswählen, bearbeiten und ziehen kann?Antwort
Richtige Antwort: Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled. Jedes Flag ist für eine bestimmte Interaktionsmöglichkeit zuständig.
Warum reicht es nicht aus, einfach die Methode sortItems() aufzurufen, um Elemente nach Datum oder numerischen Werten zu sortieren?Antwort
Richtige Antwort: Standardmäßig verwendet sortItems() alphabetische (lexikographische) Sortierung von Strings. Für korrekte Sortierung nach Datum oder Zahlen muss die Item-Klasse abgeleitet und der operator<() überschrieben werden, um Werte korrekt zu vergleichen.
In welchen Situationen ist QComboBox gegenüber QListWidget vorzuziehen, auch wenn sie funktional ähnlich sind?Antwort
Richtige Antwort: Wenn Platzersparnis in der Benutzeroberfläche wichtig ist und der Benutzer nur ein Element aus der Liste auswählen muss. QComboBox zeigt nur die aktuelle Auswahl an und klappt sich nur zum Zeitpunkt der Auswahl auf.
Warum sollte man die Checkbox-Darstellung über Qt::ItemIsUserCheckable verwenden statt ein echtes QCheckBox-Widget hinzuzufügen?Antwort
Richtige Antwort: Dies verbessert die Performance der Liste erheblich, besonders bei einer großen Anzahl von Elementen (Hunderte und mehr). Die Checkbox-Darstellung erstellt kein echtes Widget, sondern rendert nur dessen Aussehen.
Was ist der Unterschied zwischen den Signalen activated() und currentIndexChanged() in QComboBox?Antwort
Richtige Antwort: activated() wird bei jeder Auswahl gesendet, auch wenn der Benutzer dasselbe Element erneut auswählt. currentIndexChanged() wird nur bei einer tatsächlichen Änderung des aktuellen Elements gesendet.
Was passiert, wenn sortItems() aufgerufen wird und dann neue Elemente mit der Methode addItem() zur Liste hinzugefügt werden?Antwort
Richtige Antwort: Neue Elemente werden nicht automatisch sortiert und werden am Ende der Liste hinzugefügt. Ein erneuter Aufruf von sortItems() ist erforderlich, um alle Elemente zu sortieren.
Wie setzt man den Mehrfachauswahl-Modus für QListWidget oder QTreeWidget?Antwort
Richtige Antwort: Die Methode setSelectionMode() mit dem Parameter QAbstractItemView::MultiSelection aufrufen. Für Verbot der Auswahl wird NoSelection verwendet, für die Auswahl nur eines Elements – SingleSelection.
Welche Methode ermöglicht es, die Liste aller ausgewählten Elemente in QListWidget zu erhalten, wenn der Mehrfachauswahl-Modus aktiviert ist?Antwort
Richtige Antwort: Die Methode selectedItems() gibt eine Liste aller ausgewählten Elemente zurück. Für ein einzelnes aktuelles Element wird currentItem() verwendet.
Wozu wird in QTreeWidget der QTreeWidgetItemIterator verwendet, und welches Flag muss übergeben werden, um nur ausgewählte Elemente zu durchlaufen?Antwort
Richtige Antwort: Der Iterator ermöglicht es, einfach alle Elemente des Baums zu durchlaufen, einschließlich verschachtelter. Um nur ausgewählte Elemente zu durchlaufen, muss das Flag QTreeWidgetItemIterator::Selected an den Konstruktor des Iterators übergeben werden.
Wofür ist die Klasse QTabWidget gedacht, und in welchen Situationen ist ihre Verwendung am meisten gerechtfertigt?Antwort
Richtige Antwort: QTabWidget teilt ein komplexes Dialogfenster mit vielen Optionen in eine Reihe logisch zusammengestellter einfacher Fenster auf und macht die Benutzeroberfläche verständlicher und benutzerfreundlicher.
Wie prüft man, ob die Checkbox in einem Element einer hierarchischen Liste mit Checkbox-Darstellung aktiviert ist?Antwort
Richtige Antwort: Man muss die Methode checkState() mit der Spaltennummer aufrufen und das Ergebnis mit Qt::Checked vergleichen: if (ptwi->checkState(0) == Qt::Checked).
Praktische Aufgaben
Einfaches Level
Verzeichnis mit Kategorien
Erstellen Sie eine Anwendung mit einer Dropdown-Liste (QComboBox), die Kategorien enthält: “Obst”, “Gemüse”, “Beeren”. Bei Auswahl einer Kategorie sollen in einer einfachen Liste (QListWidget) die entsprechenden Elemente angezeigt werden. Zum Beispiel für “Obst”: Apfel, Banane, Orange. Fügen Sie Icons zu den Listenelementen hinzu.
Hinweise: Verwenden Sie das Signal currentIndexChanged() von QComboBox, um die Kategorieauswahl zu verfolgen. Bei Kategoriewechsel löschen Sie die Liste mit clear() und füllen Sie sie mit neuen Elementen. Für Icons verwenden Sie QListWidgetItem::setIcon(). Speichern Sie Daten in QMap<QString, QStringList> für Bequemlichkeit.
Mittleres Level
Aufgabenmanager mit Prioritäten
Entwickeln Sie einen Aufgabenmanager basierend auf QTableWidget mit drei Spalten: “Aufgabe”, “Priorität”, “Status”. Der Benutzer sollte in der Lage sein, neue Aufgaben über QLineEdit hinzuzufügen, die Priorität aus QComboBox (niedrig/mittel/hoch) auszuwählen und die Erledigung über eine Checkbox in der Zelle zu markieren. Implementieren Sie die Sortierung nach Priorität bei Klick auf die Spaltenüberschrift. Fügen Sie einen Button zum Löschen der ausgewählten Zeile hinzu.
Hinweise: Verwenden Sie setSortingEnabled(true) für die Tabelle. Für Checkboxen verwenden Sie setCheckState() auf QTableWidgetItem. Zum Löschen einer Zeile verwenden Sie removeRow() mit dem Index aus currentRow(). Für benutzerdefinierte Sortierung nach Priorität erstellen Sie eine Ableitung von QTableWidgetItem mit überladenem operator<().
Schwieriges Level
Datei-Navigator mit Drag & Drop
Erstellen Sie einen zweifenstrigen Datei-Navigator mit QTreeWidget. Das linke Panel zeigt die Ordnerhierarchie (mindestens 3 Verschachtelungsebenen), das rechte – den Inhalt des ausgewählten Ordners im Icon-Modus (QListWidget mit IconMode). Implementieren Sie das Ziehen von Dateien zwischen den Panels mit visueller Indikation. Bei Doppelklick auf einen Ordner im rechten Panel sollte dieser im linken geöffnet werden. Fügen Sie ein Kontextmenü mit den Optionen “Ordner erstellen”, “Umbenennen”, “Löschen” hinzu. Verwenden Sie QTabWidget zur Organisation mehrerer geöffneter Ordner.
Hinweise: Aktivieren Sie Drag & Drop über setDragEnabled(true) und setAcceptDrops(true). Behandeln Sie dropEvent() für die Reaktion auf Ziehen. Verwenden Sie das Signal itemClicked() zur Synchronisation der Panels. Für das Kontextmenü erstellen Sie QMenu und zeigen Sie es im Handler contextMenuEvent(). Speichern Sie den Ordnerpfad in QTreeWidgetItem über setData(). Für Tabs verwenden Sie addTab() mit eindeutigen Panel-Instanzen.
💬 Beteiligen Sie sich an der Diskussion!
Haben Sie die Auswahlelemente verstanden? Fragen dazu, wann man QListWidget verwenden sollte und wann es besser ist, zur Model-View-Architektur überzugehen?
Teilen Sie Ihre Lösungen für praktische Aufgaben, diskutieren Sie die Feinheiten der Performance-Optimierung von Listen und helfen Sie anderen Lesern, das Material des Kapitels zu meistern!
Ihre Erfahrung und Fragen helfen der gesamten Community, Qt besser zu verstehen!