QAbstractItemModel 动态项插入

QAbstractItemModel dynamic item insertion

本文关键字:插入 动态 QAbstractItemModel      更新时间:2023-10-16

我为我的模型继承了QAbstractItemModel类。为了轻松地将新项目插入模型,我编写了下一个方法:

void addItem(MyData *parent, MyData *children) {
    QModelIndex idx = createIndex(parent->row(), 0, parent);
    if (!idx.isValid()) {
        return;
    }
    int childCount = parent->getChildCount();
    beginInsertRows(idx, childCount, childCount);
    parent->addChild(children);
    endInsertRows();
    emit layoutChanged(QList<QPersistentModelIndex>{idx});
}

它与QListView配合得很好,但是QML的TreeView在显示它之后不会更新值:

int main(int argc, char ** argv) {
    Q_INIT_RESOURCE(ui);
    QApplication application(argc, argv);
    MyModel model;
    for (int i = 0; i < 10; ++ i) {
        MyData *firstLevelItem = new MyData(i);
        for (int k = 0; k < 3; ++ k) {
            MyData *secondLevelItem = new MyData(i);
            model.addItem(firstLevelItem, secondLevelItem);
        }
        model.addItem(model.getRootItem(), firstLevelItem);
    }
    QQuickView view;
    QQmlContext *context = view.rootContext();
    context->setContextProperty("MyModel", &model);
    view.setSource(QUrl("qrc:///ui/form.qml"));
    view.show();
    QTreeView t;
    t.setModel(&model);
    t.show();
    MyData *data = new MyData(2281488);
    model.addItem(model.getRootItem(), data);
    // t displays changes, view - not
    return application.exec();
}

我的数据类:

class MyModel;
class MyData: public QObject {
    Q_OBJECT
public:
    explicit MyData() :
        QObject() {
        _parent = nullptr;
    }
    ~MyData() {
        qDeleteAll(_data);
    }
    // getters / setters
    MyData *getChildItem(int index) const {
        if (index < 0 || index >= _data.size()) {
            return nullptr;
        }
        return _data[index];
    }
    int getChildCount() const {
        return _data.size();
    }
    MyData *parent() const {
        return _parent;
    }
    int row() const {
        if (_parent) {
            return _parent->_data.indexOf(const_cast<MyData *>(this));
        } else {
            return 0;
        }
    }
private:
    void addChild(MyData *data) {
        if (data) {
            if (data->_parent) {
                _parent->removeChild(data);
            }
            data->_parent = this;
            _data << data;
        }
    }
    void removeChild(MyData *data) {
        _data.removeAll(data);
    }
    // some private fields
    MyData *_parent;
    QVector<MyData *> _data;
    friend class MyModel;
};
例如,

QML的ListView不适合显示树状结构,例如目录树。它仅适用于通常继承自 QAbstractListModel 的列表模型。如果从 QAbstractItemModel 派生模型,则必须对其进行专用化,使其行为类似于列表。

从Qt 5.5开始,在QtQuick.Controls模块(v1.4)中有一个QML TreeView组件。你可能想试试这个。