所以我有了使用 QObjects 的 Q_PROPERTY
而不是 QAbstractListModel
的角色名称的想法,以便将可通知的属性公开给 QML。
我的问题是这是否是一个好的做法,因为使用从 QAbstractItemModel
继承的类感觉有点不自然。
让我更详细地解释一下。
因此,为 QML 创建 C++ 模型的推荐方法是:
- 继承
QAbstractListModel
(或其他)以创建您的自定义模型。 - 重载
rowCount()
- 定义您自己的数据角色。
例如:
enum DataRoles {
Name = Qt::UserRole + 1,
Description,
CustomData
};
...
QHash<int, QByteArray> TestList::roleNames() const
{
QHash<int, QByteArray> res;
res[static_cast<int>(DataRoles::Name)] = "name";
res[static_cast<int>(DataRoles::Description)] = "description";
res[static_cast<int>(DataRoles::CustomData)] = "customData";
return res;
}
- 在重载的
data()
成员函数中返回相应的数据。
例如:
QVariant TestList::data(const QModelIndex & index, int role) const
{
QVariant result = QVariant();
if ( index.isValid() == true ) {
EntityPtr entityPtr = entities_.at(index.row());
switch (role) {
case DataRoles::Name:
result = entityPtr->name();
break;
case DataRoles::Description:
result = entityPtr->description();
break;
case DataRoles::CustomData:
result = entityPtr->customData();
break;
}
}
return result;
}
然后,在 QML 上下文中注册您的模型实例后,您可以按名称访问 ListView 委托(delegate)中的实体字段,该名称在 rolesNames() 中定义,例如:
ListView {
model: yourModelInstance
...
delegate: Item {
...
Text {
text: name // access DataRoles::Name
}
...
}
}
IMO,这个实现很好,但是当涉及到从 C++ 端更改属性时,您应该在每次实体属性更改时调用 QAbstractListView
的 dataChaged() 信号.
我希望能够自动通知 View 有关更改,例如当我调用 entity->setName()
时。
我的想法是只注册一个数据角色,例如“对象”将返回整个 QObject,它将具有 Q_PROPERTY
,然后从 qml 中访问它,如:
Text {
text: object.name //access `name` Q_PROPERTY of the object
}
这样,如果 setter 发出正确的信号,在 Q_PROPERTY 声明中注册,QML 端将自动通知有关设置新值的更改。
所以问题是,这是否是实现我目标的好方法,因为正如我上面所说,感觉有点不自然,而 Qt 库可以很好地表明你做错了什么做错事很难(不自然)。
编辑:
按照评论中的要求,我制作了一个小型 Qt 示例应用程序来展示我想要实现的目标。
最佳答案
我认为您需要在 Entity 中为每个属性提供一个 propertyChanged 信号。然后将 propertyChanged 链接到 dataChanged 信号。当您设置名称或设置位置时,发出 propertyChanged 信号。
关于c++ - 为 QML 的 ListView 公开 QObjects 的 QAbstractListModel。好的做法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35797732/