Fetch More Beispiel
Das Beispiel "Fetch More" zeigt, wie man einem Modell der Elementansicht bei Bedarf Elemente hinzufügt.
Wenn Sie große - oder vielleicht sogar unendliche - Datensätze haben, müssen Sie dem Modell Elemente stapelweise hinzufügen, und vorzugsweise nur dann, wenn die Elemente von der Ansicht benötigt werden (d.h. wenn sie in der Ansicht sichtbar werden).
In diesem Beispiel implementieren wir FileListModel
- ein Item-View-Modell, das die Einträge eines Verzeichnisses enthält. Wir haben auch Window
, das die Benutzeroberfläche einrichtet und das Modell mit Verzeichnissen füttert.
Die Benutzeroberfläche besteht aus einem Dialog mit einer Liste, die den Inhalt des Stammverzeichnisses anzeigt. Verzeichnisse können durch Doppelklick navigiert werden.
Unten befindet sich ein Protokollfenster, das Meldungen anzeigt, wenn die Ansicht das Modell um weitere Daten bittet.
Navigieren Sie dazu zu einem großen Verzeichnis (z. B. /bin
) und blättern Sie bis zum Ende. Es erscheinen Protokollmeldungen, die die abgerufenen Daten anzeigen.
Werfen wir einen Blick auf den Code von FileListModel
.
FileListModel-Klassendefinition
Die Klasse FileListModel
erbt von QAbstractListModel und enthält den Inhalt eines Verzeichnisses. Es fügt sich selbst nur dann Elemente hinzu, wenn es von der Ansicht dazu aufgefordert wird.
class FileListModel : public QAbstractListModel { Q_OBJECT public: FileListModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QFileInfo fileInfoAt(const QModelIndex &) const; signals: void numberPopulated(const QString &path, int start, int number, int total); public slots: void setDirPath(const QString &path); protected: bool canFetchMore(const QModelIndex &parent) const override; void fetchMore(const QModelIndex &parent) override; private: QFileInfoList fileList; QString path; QFileIconProvider iconProvider; int fileCount = 0; };
Das Geheimnis liegt in der Neuimplementierung von fetchMore() und canFetchMore() von QAbstractItemModel. Diese Funktionen werden von der Elementansicht aufgerufen, wenn sie weitere Elemente benötigt.
Die Funktion setDirPath()
legt das Verzeichnis fest, mit dem das Modell arbeiten soll. Wir geben numberPopulated()
jedes Mal aus, wenn wir dem Modell einen Stapel von Elementen hinzufügen.
Wir behalten alle Verzeichniseinträge in fileList
. fileCount
ist die Anzahl der Elemente, die dem Modell hinzugefügt wurden.
Implementierung der FileListModel-Klasse
Wir beginnen mit dem Auschecken der setDirPath()
.
void FileListModel::setDirPath(const QString &path) { QDir dir(path); beginResetModel(); this->path = path; fileList = dir.entryInfoList(QDir::NoDot | QDir::AllEntries, QDir::Name); fileCount = 0; endResetModel(); }
Wir verwenden QDir, um den Inhalt des Verzeichnisses abzurufen. Wir müssen QAbstractItemModel mitteilen, dass wir alle Elemente - falls vorhanden - aus dem Modell entfernen wollen.
bool FileListModel::canFetchMore(const QModelIndex &parent) const { if (parent.isValid()) return false; return (fileCount < fileList.size()); }
Die Funktion canFetchMore()
wird von der Ansicht aufgerufen, wenn sie weitere Einträge benötigt. Wir geben true zurück, wenn es noch Einträge gibt, die wir dem Modell nicht hinzugefügt haben; andernfalls geben wir false zurück.
Und nun die Funktion fetchMore()
selbst:
void FileListModel::fetchMore(const QModelIndex &parent) { if (parent.isValid()) return; const int start = fileCount; const int remainder = int(fileList.size()) - start; const int itemsToFetch = qMin(batchSize, remainder); if (itemsToFetch <= 0) return; beginInsertRows(QModelIndex(), start, start + itemsToFetch - 1); fileCount += itemsToFetch; endInsertRows(); emit numberPopulated(path, start, itemsToFetch, int(fileList.size())); }
Zunächst berechnen wir die Anzahl der abzurufenden Elemente. beginInsertRows() und endInsertRows() sind obligatorisch für QAbstractItemModel, um mit den Zeileneinfügungen Schritt zu halten. Schließlich geben wir numberPopulated()
aus, das von Window
abgeholt wird.
Um die Tour zu vervollständigen, schauen wir uns auch rowCount()
und data()
an.
int FileListModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : fileCount; } QVariant FileListModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return {}; const int row = index.row(); if (row >= fileList.size() || row < 0) return {}; switch (role) { case Qt::DisplayRole: return fileList.at(row).fileName(); case Qt::BackgroundRole: { const int batch = row / batchSize; const QPalette &palette = QGuiApplication::palette(); return (batch % 2) != 0 ? palette.alternateBase() : palette.base(); } case Qt::DecorationRole: return iconProvider.icon(fileList.at(row)); } return {}; }
Beachten Sie, dass die Zeilenzählung nur die bisher hinzugefügten Elemente angibt, also nicht die Anzahl der Einträge im Verzeichnis.
In data()
geben wir den entsprechenden Eintrag aus fileList
zurück. Außerdem trennen wir die Stapel durch eine andere Hintergrundfarbe.
© 2025 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.