Kapitel 12. Interview oder Model-View

Kennen Sie die Situation, in der derselbe Datensatz in mehrere Widgets „gestopft” werden muss – und plötzlich schwillt die Anwendung im Speicherverbrauch an und die Synchronisation wird zum Albtraum? Besonders spürbar ist dies beim Dateisystem und beliebigen „schweren” Datenquellen: Die Duplizierung wächst, Bugs vermehren sich, und Änderungen in der Datenspeicherlogik ziehen eine Kaskade von Anpassungen nach sich.

Dieses Kapitel enthüllt, warum der Qt-Ansatz „Interview” (Model/View) nicht nur ein Muster aus Lehrbüchern ist, sondern ein praktisches Werkzeug, mit dem professionelle Entwickler Performance und Architektur retten. Hier entdecken Sie ein nicht offensichtliches Geheimnis: wie man Daten von der Darstellung so trennt, dass man das Speicher-Backend fast schmerzfrei ändern kann – und dabei sauberen, testfreundlichen Code erhält.

Es werden 4 Schlüsselkomponenten behandelt (Model, View, Selection, Delegate), die Arbeit mit QModelIndex und Rollen (DisplayRole/ToolTipRole/DecorationRole), sowie Sortierung/Filterung über QSortFilterProxyModel. Plus – praktische Beispiele: Teilen der Auswahl zwischen 3 Views, ein custom Delegate mit Highlighting und ein Mini-Dateisystem-Browser auf Basis von QFileSystemModel.

Wenn Model-View immer noch wie „komplizierte Magie” erscheint – dieses Kapitel zu überspringen bedeutet, weiterhin mit Zeit und Speicher in jedem zweiten Projekt zu bezahlen.

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

Selbsttest zum Kapitel

Warum ist die „Interview”-Technologie effizienter als der item-basierte Ansatz bei der Arbeit mit Datenbanken und großen Datenmengen?Antwort
Richtige Antwort: Daten werden nicht dupliziert, wenn mehrere Views verwendet werden – alle Views arbeiten mit einem Datenmodell über das Interface. Dies spart Speicher und löst automatisch das Synchronisationsproblem.
Welche zwei Methoden müssen obligatorisch implementiert werden, wenn man ein eigenes Model basierend auf QAbstractListModel erstellt?Antwort
Richtige Antwort: Die Methoden rowCount() (gibt die Anzahl der Zeilen zurück) und data() (gibt Daten für einen bestimmten Index und eine Rolle zurück). Ohne sie kann das Model keine Daten an Views liefern.
Was ist ein Proxy-Model und wozu wird es benötigt?Antwort
Richtige Antwort: Dies ist ein Model zwischen dem Quell-Model und der View, das Sortierung und Filterung von Daten ermöglicht, ohne das Original-Model zu ändern. Die Klasse QSortFilterProxyModel ist eine fertige Implementierung für diese Aufgaben.
Warum muss beim Ändern von Daten über die Methode setData() das Signal dataChanged() gesendet werden?Antwort
Richtige Antwort: Das Signal benachrichtigt alle verbundenen Views darüber, dass sich Daten geändert haben und sie ihren Inhalt aktualisieren müssen. Ohne dieses Signal werden Änderungen nicht in der Benutzeroberfläche angezeigt.
Aus welchen drei Teilen besteht ein Model-Index (QModelIndex)?Antwort
Richtige Antwort: Aus Zeile, Spalte und interner ID. Dies ermöglicht es, Zellen in hierarchischen Tabellen zu adressieren, wobei die interne ID auf das Eltern-Element verweist.
Warum müssen beginInsertRows() und endInsertRows() beim Einfügen von Zeilen in ein Model aufgerufen werden?Antwort
Richtige Antwort: Diese Methoden benachrichtigen alle verbundenen Views und andere Objekte über den Beginn und Abschluss von Änderungen im Model, was es ihnen ermöglicht, ihren Zustand korrekt zu aktualisieren und Darstellungsfehler zu vermeiden.
Welche Rolle spielt der Delegate in der Model-View-Architektur und welche Methode muss überladen werden, um das Aussehen der Elemente zu ändern?Antwort
Richtige Antwort: Der Delegate ist für das Zeichnen jedes Elements und dessen Bearbeitung verantwortlich. Um das Aussehen zu ändern, muss die Methode paint() überladen werden, die QPainter und Darstellungsparameter erhält.
Wie macht man Model-Elemente vom Benutzer bearbeitbar?Antwort
Richtige Antwort: Implementieren Sie die Methode setData() zum Speichern von Änderungen und überschreiben Sie die Methode flags(), sodass sie das Flag Qt::ItemIsEditable für gültige Indizes zurückgibt.
Warum muss in der Methode rowCount() für ein Listen-Model 0 zurückgegeben werden, wenn parent.isValid() gleich true ist?Antwort
Richtige Antwort: Ein Listen-Model (QAbstractListModel) ist per Definition eindimensional und sollte keine Kind-Elemente haben. Ein gültiger Eltern-Index zeigt einen Versuch an, Kind-Elemente abzurufen, die nicht existieren sollten.
Welche Vorteile bietet die zentrale Verwaltung der Auswahl über QItemSelectionModel?Antwort
Richtige Antwort: Es ermöglicht das Teilen des Auswahlmechanismus zwischen mehreren Views eines Models – die Auswahl eines Elements in einer View wird automatisch in allen anderen widergespiegelt. Der Code zur Verwaltung der Auswahl befindet sich an einer Stelle.
Wofür werden Element-Rollen verwendet (z.B. Qt::DisplayRole, Qt::EditRole)?Antwort
Richtige Antwort: Rollen ermöglichen es jedem Model-Element, verschiedene Datentypen für verschiedene Zwecke zu speichern: Text zur Anzeige, Wert zur Bearbeitung, Icon, Hintergrundfarbe, Tooltip usw.
In welchem Fall sollte QStandardItemModel anstelle der Erstellung eines eigenen Models verwendet werden?Antwort
Richtige Antwort: Wenn man mit einer kleinen Datenmenge arbeiten muss und es bequemer ist, Daten direkt im Model zu speichern. Dies ist eine Kompromisslösung, die der Model-View-Idee widerspricht, aber für einfache Anwendungen praktisch ist.
Wie kann man auf das eingebaute Model eines item-basierten Widgets QListWidget zugreifen und wozu könnte das nötig sein?Antwort
Richtige Antwort: Rufen Sie die Methode model() auf, die einen Zeiger auf das eingebaute Model zurückgibt. Dies ermöglicht es, die Daten von QListWidget mit anderen Views zu teilen, ohne sie zu duplizieren.

Praktische Aufgaben

Einfaches Level

Aufgabenliste mit geteilten Views
Erstellen Sie eine Anwendung für eine Aufgabenliste mit QStringListModel. Zeigen Sie dieses Model gleichzeitig in QListView und QTableView an. Fügen Sie 5 anfängliche Aufgaben hinzu. Stellen Sie sicher, dass die Auswahl eines Elements in einer View es automatisch auch in der anderen auswählt.
Hinweise: Verwenden Sie QStringListModel und die Methode setStringList() zur Initialisierung der Daten. Erstellen Sie ein QItemSelectionModel und setzen Sie es in beide Views mit der Methode setSelectionModel(). Vergessen Sie nicht, das Model in beide Views über setModel() zu setzen.

Mittleres Level

Kontakte-Model mit Filterung
Erstellen Sie eine Anwendung mit einem Kontakte-Model (Personennamen). Verwenden Sie QStringListModel mit 10-15 Namen. Fügen Sie ein QLineEdit für die Filtereingabe und zwei QListView-Views hinzu: eine zeigt alle Kontakte, die andere – nur die gefilterten. Bei Texteingabe in QLineEdit sollte die zweite View nur Namen anzeigen, die den eingegebenen Text enthalten.
Hinweise: Verwenden Sie QSortFilterProxyModel für die Filterung. Erstellen Sie das Original-Model QStringListModel und ein Proxy-Model, das über setSourceModel() damit verbunden ist. Verbinden Sie das Signal textChanged() von QLineEdit mit dem Slot setFilterWildcard() oder setFilterRegularExpression() des Proxy-Models.

Schwieriges Level

Eigenes Studenten-Model mit Noten
Erstellen Sie ein eigenes Tabellen-Model basierend auf QAbstractTableModel zur Speicherung von Studenteninformationen: Name, Alter und Durchschnittsnote. Das Model muss die Bearbeitung aller Felder unterstützen. Implementieren Sie die Methoden data(), setData(), rowCount(), columnCount(), headerData() und flags(). Fügen Sie die Möglichkeit hinzu, neue Zeilen über einen Button einzufügen. Zeigen Sie das Model in QTableView mit einem custom Delegate an, der Zeilen von Studenten mit einer Note über 4.5 mit grünem Hintergrund hervorhebt.
Hinweise: Speichern Sie Daten in QVector> oder erstellen Sie eine Student-Struktur. Behandeln Sie in der Methode data() die Rollen Qt::DisplayRole und Qt::EditRole. Für die Bearbeitung geben Sie Qt::ItemIsEditable in flags() zurück. Implementieren Sie insertRows() mit Aufrufen von beginInsertRows()/endInsertRows(). Für den Delegate erben Sie von QStyledItemDelegate und überladen Sie die Methode paint(), wobei Sie den Notenwert über index.data() prüfen.

💬 Beteiligen Sie sich an der Diskussion!

Haben Sie die Model-View-Architektur verstanden? Gelang es Ihnen, Ihr erstes Model basierend auf QAbstractListModel oder QAbstractTableModel zu erstellen?

Haben Sie Fragen dazu, wann Proxy-Models verwendet werden sollten, wie man richtig mit Element-Rollen arbeitet oder wie man einen custom Delegate implementiert?

Teilen Sie Ihre Erfahrung: Welche Aufgaben haben Sie mit Model-View gelöst? Sind Sie auf Probleme bei der Erstellung eigener Models gestoßen? Welche Patterns waren in Ihrer Praxis am nützlichsten?

Ihre Fragen und Erkenntnisse helfen anderen Lesern, diese mächtige Qt-Technologie besser zu meistern!

Leave a Reply

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