我有一个QList<QObject*>包含自定义对象并暴露给QML 的C++模型.
我的自定义对象如下所示:
class CustomObject : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ getName NOTIFY nameChanged)
Q_PROPERTY(QQmlListProperty<CustomObject READ getChildren NOTIFY childrenChanged)
[...]
}
Run Code Online (Sandbox Code Playgroud)
我的模型接触到QML,如下所示:
qmlEngine->rootContext()->setContextProperty("internalModel", QVariant::fromValue(m_internalModel));
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.我可以使用视图,显示我的所有元素,并递归地显示他们的孩子.
问题是QList无法通知QML模型已更改.如关于基于QObjectList的模型的文档中所述:
注意:视图无法知道QList的内容已更改.如果QList发生变化,则需要通过再次调用QQmlContext :: setContextProperty()来重置模型.
所以每当我添加或删除一个项目时,我都会打电话:
qmlEngine->rootContext()->setContextProperty("internalModel", QVariant::fromValue(m_internalModel));
Run Code Online (Sandbox Code Playgroud)
这非常慢.
如果我理解正确,我需要改为使用QAbstractItemModel.
那么,是不是可以从迁移QList<QObject*>到QAbstractItemModel不改变QML一部分?特别是,我应该将所有Q_PROPERTY从CustomObject 迁移到角色还是可以"重用它们"?
是的,这是可能的,你只需要稍微改变QML
C++模型类
#pragma once
#include <QAbstractListModel>
#include <QVector>
class Model : public QAbstractListModel {
Q_OBJECT
public:
int rowCount(const QModelIndex&) const override;
QVariant data(const QModelIndex& index, int role) const override;
public slots:
void insert(QObject* item);
void remove(QObject* item);
protected:
QHash<int, QByteArray> roleNames() const override;
private:
QVector<QObject*> mItems;
};
Run Code Online (Sandbox Code Playgroud)
它适用于任何继承的类型QObject.您可以插入并通过删除项目insert()和remove()其无论是从C++和QML工作.实现非常简单
#include "model.h"
int Model::rowCount(const QModelIndex&) const {
return mItems.size();
}
QVariant Model::data(const QModelIndex& index, int /*role*/) const {
QObject* item = mItems.at(index.row());
return QVariant::fromValue(item);
}
void Model::insert(QObject* item) {
beginInsertRows(QModelIndex(), 0, 0);
mItems.push_front(item);
endInsertRows();
}
void Model::remove(QObject* item) {
for (int i = 0; i < mItems.size(); ++i) {
if (mItems.at(i) == item) {
beginRemoveRows(QModelIndex(), i, i);
mItems.remove(i);
endRemoveRows();
break;
}
}
}
QHash<int, QByteArray> Model::roleNames() const {
QHash<int, QByteArray> roles;
roles[Qt::UserRole + 1] = "item";
return roles;
}
Run Code Online (Sandbox Code Playgroud)
注意使用roleNames()和"item"角色.我们将在QML中使用它.您不需要将CustomObject属性迁移到角色,只需使用单个角色并QObject*从中返回指针Model::data().
型号注册
Model internalModel;
qmlEngine->rootContext()->setContextProperty("internalModel", &internalModel);
Run Code Online (Sandbox Code Playgroud)
最后
ListView {
model: internalModel
delegate: Text {
text: model.item.name
}
}
Run Code Online (Sandbox Code Playgroud)
您在QML中唯一需要做的就是替换name和getChildren使用model.item.name和model.item.getChildren.听起来很简单?
| 归档时间: |
|
| 查看次数: |
2134 次 |
| 最近记录: |