Modelle und Ansichten: Listenmodell mit einem Worker-Thread zum Abrufen von Daten
Veranschaulicht, wie ein Listenmodell mit einer reaktionsschnellen Benutzeroberfläche implementiert wird, wobei ein Worker-Thread zum Abrufen von Daten verwendet wird.

Dieses Beispiel stellt ein benutzerdefiniertes Elementmodell vor, das von „ QAbstractListModel “ erbt. Das Modell bezieht seine Daten von einem Worker-Objekt, das sich in einem separaten „ QThread “ befindet und Daten aus einer langsamen Datenquelle abruft.
Übersicht über das Beispiel „Threaded Song List“
Die Datenquelle simuliert eine langsame Datenquelle, indem sie pro abgerufenem Titel eine Verzögerung von 100 Millisekunden einbaut. Das bedeutet, dass das Laden der gesamten Liste mit 3.600 Titeln 6 Minuten dauern würde, was das Öffnen der Anwendung unpraktisch machen würde. Diese Verzögerung wird gemildert, indem die Daten nur für den sichtbaren Bereich der Ansicht abgerufen werden – mithilfe eines „ QObject “, der in einem Worker-Thread platziert ist.
Das Worker-Objekt verfügt über eine Begrenzung für die Anzahl der Abrufanfragen, die es in der Warteschlange hält. Dies stellt sicher, dass nur die Elemente des aktuell sichtbaren Teils der Songliste abgerufen werden, wodurch die Notwendigkeit entfällt, auf das Laden des nicht sichtbaren Teils der Liste zu warten, wenn der Benutzer bereits an einem Teil der Liste vorbeigescrollt hat.
Der Schwerpunkt dieses Beispiels liegt auf dem Quellmodell der Ansicht. Die Ansicht selbst ist ein unveränderter QML- ListView mit einem einfachen Delegaten. Die Verwendung eines Threads ist hinter der Implementierung der Modelldatenverarbeitung verborgen, und der „ ListView “ muss nicht angepasst werden, um sich an das threadbasierte Modell anzupassen.
Da der Schwerpunkt zudem auf dem Modell liegt, ist die „ Qt Quick Controls “ so eingestellt, dass sie auf allen Plattformen den „Universal“-Stil verwendet, um ein identisches UI-Verhalten zu gewährleisten.
import QtQuick
import QtQuick.Controls.UniversalSo funktioniert es
Die Geschäftslogik zur Bereitstellung der Songlistendaten ist in die Klasse „ DataStorage “ ausgelagert, die eine einfache, ID-basierte Schnittstelle für das Modell bereitstellt.
QList<int> idList();
MediaElement item(int id) const;
std::optional<int> currentlyFetchedId() const;Wenn das Modell Daten vom „DataStorage“ anfordert, prüft der Speicher zunächst, ob die Daten bereits verfügbar sind. Ist dies der Fall, werden die Daten sofort zurückgegeben, wie es auch bei einem nicht-threadbasierten Modell der Fall wäre. Falls die Daten nicht gefunden werden, sendet der „DataStorage“ ein „ dataFetchNeeded() “-Signal an das Worker-Objekt und fügt der Liste der bereits vorhandenen Daten ein leeres Element hinzu. Das Hinzufügen des leeren Eintrags stellt sicher, dass keine weiteren Signale für denselben Listenposten an den Worker gesendet werden.
if (!m_items.contains(id)) {
m_items.insert(id, MediaElement{});
emit dataFetchNeeded(m_idList.indexOf(id));
}
return m_items.value(id);QueueWorker - Das Worker-Thread-Objekt verarbeitet die empfangenen `dataFetchNeeded()`-Signale, indem es ein Signal an sich selbst sendet. Dadurch ist es möglich, alle bereits in der `QEventQueue` befindlichen Signale zu empfangen, bevor der langsame Datenlesevorgang gestartet wird.
Anwendung des Ansatzes auf dynamische Modelle
Wenn man die Lösung auf einen Fall ausweiten möchte, in dem Elemente zur Datenquelle (in diesem Fall „RemoteMedia“) hinzugefügt, verschoben oder daraus entfernt werden können, muss „DataStorage“ mit Signalen aktualisiert werden, die den Funktionen „ QAbstractItemModel::rowsMoved()“, „ QAbstractItemModel::rowsInserted()“ sowie zwei Signalen entsprechen, um die Methoden „ QAbstractItemModel::beginRemoveRows()“ und „ QAbstractItemModel::endRemoveRows()“ innerhalb von „ThreadedListModel“ auszulösen.
Für das Einfügen und Verschieben kann das `ThreadedListModel` einfach ` QAbstractItemModel::beginInsertRows()` aufrufen, anschließend neue IDs zu seiner ID-Liste hinzufügen und ` QAbstractItemModel::endInsertRows()` aufrufen. Da das `ThreadedListModel` eine Kopie der ID-Liste enthält und über die ID auf den Speicher zugreift, ist es nicht erforderlich, den Beginn und das Ende des Speichers zu signalisieren. Ebenso kann das `ThreadedListModel` ` QAbstractItemModel::beginMoveRows()` aufrufen, IDs in seiner ID-Liste verschieben und anschließend ` QAbstractItemModel::endMoveRows()` aufrufen.
Das Entfernen ist ein etwas komplexerer Fall. Die Ansicht muss die Möglichkeit haben, die Daten, die entfernt werden sollen, anzufordern, bevor sie tatsächlich entfernt werden. Daher muss „DataStorage“ eine Warnung vor dem Entfernen auslösen, wodurch das Modell „ QAbstractItemModel::beginRemoveRows()“ aufruft. In dieser Phase erhält `ThreadedListModel` möglicherweise einen oder mehrere Aufrufe von ` data() `. Sobald der Aufruf des direkt verbundenen Signals bei `DataStorage` zurückkehrt, kann `DataStorage` das Element entfernen und anschließend dem Modell erneut ein Signal senden, das das Modell dazu veranlasst, ` QAbstractItemModel::endRemoveRows()` aufzurufen.
Ausführen des Beispiels
Sie können das Beispiel wie folgt ausführen:
- Qt Creator
Öffnen Sie den Modus „ Welcome “ und wählen Sie das Beispiel unter „ Examples “ aus. Weitere Informationen finden Sie unter „Qt Creator “: Tutorial: Erstellen und Ausführen.
- Qt Extension for Visual Studio Code
Führen Sie den Befehl „ Qt: Open Qt examples “ über „ Command Palette “ aus und wählen Sie das Beispiel aus der Liste aus. Weitere Informationen finden Sie unter „Qt Extension for Visual Studio Code “: Tutorial: Erstellen und Ausführen.
© 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.