我应该使用多个角色还是一个角色将实际属性推迟到 QObject wrapping/exposing 数据作为其属性

Should I use many roles or a single one deferring the actual properties to a QObject wrapping/exposing the data as its properties

是一个 QAbstractListModel 具有角色

的实现
name, image, enabled, color, editable

比单一角色的实现更好(原谅我想不出更好的名字)

thing

这会导致返回带有上述 Q_PROPERTYQObject*

QML 端的区别是在访问值时会额外 "indirection",例如委托:

model.thing.name

model.name

我倾向于 QObject 方法,因为它将数据视图从列表模型中分离出来,并且具有重用的潜力。它也不要求您也实现 setData 函数。据我所知,"many roles" 选项没有特定的专业人士,当然除非不可能正确定义一个适当的 QObject 子类来包装数据(因为例如它在概念上对特定的意义不大例)。

Yes, you should.

使用角色最根本的原因是:这是Qt写模型的方式。

好的,这个原因并不重要 --- 除非有些事情希望您以 Qt 的方式来做...

因此,您应该实现角色是有原因的,但这并不意味着您必须在 QML 中使用它们 - 取决于您打算如何处理您的模型,就没有必要了。

在我看来,最重要的原因是,您必须实施 dataChanged 信号。如果你不这样做,你的模型价值与 QVariantList.

一样多

对象属性的更改只会反映在生成的委托中,但依赖 dataChanged 信号的对象不会收到更新 - 除非您为对象触发它- 当该对象的 属性 发生变化时的作用。
另一方面,这将对委托产生重大影响,因为必须重新评估所有绑定。

QSortFilterProxyModel 为例 - 如果您没有 dataChanged 信号,它不会更新过滤器或排序,如果值已更改,因为它是为此收听 dataChanged-信号。

特设,我不知道任何其他情况会使用 Qt 库中的那个,但可能还有其他情况。

但是,只要您不打算使用其中任何一个 - 您就不需要触发 dataChanged-信号。

您是否必须为此真正实现角色,我不知道。我没有尝试在没有角色的情况下实现 dataChanged-信号。

Code of QSortFilterProxyModel, that uses the dataChanged-signal


You don't need to
When you either don't use anything that relies on properly implemented roles or you reimplement that functionality that would rely on the roles your self.

使用角色意味着您必须遵守预定义的模型模式。

如果您的对象是低级别的,那么角色是很好的选择,因此您可以将各种对象成员公开为角色。

但对于 QObject * 模型,这完全没有必要。您已经在使用 Qt 的元对象系统,它可以与 QML 引擎结合使用以促进相同的功能。

只要正确实现属性并具有通知信号,它就可以在 QML 中无缝运行。

而且它也可以节省大量时间,因为该模型是通用的,您可以使用在 QML 中定义的对象填充它,而无需重新编译 C++ 代码或为每个模型设置专用模型。

请记住,QObject 相当大,如果您有大量模型项,则会产生很大的开销。如果你的模型很大,或者你正在处理一个已经存在的数据集,而这些数据集不是开箱即用的 QObject*s,那么使用角色和诸如此类的东西来实现 "classical" 模型会更有效。

只要您不 运行 陷入其局限性,我认为单一角色 QObject* 模型是更简单、更容易、更快、更灵活和更优雅的解决方案。

至于提到的排序和过滤问题,库存解决方案显然不会解决它。如前所述 ,可以实现排序和过滤,它接受一个 JS 仿函数,您可以在其中 运行 您的自定义逻辑,我敢说这实际上比基于角色的功能更好。同样,您无需重新编译即可在其中获取新代码,甚至可以通过在 运行 时间生成的函子来驱动它。

当您想将模型与依赖于角色的功能一起使用时,在模型中加入角色会很有帮助。

例如,您想将模型提供给 ComboBox,如果它有角色,您只需将 textRole 指定给 ComboBox,它就会执行它的操作。如果使用单个对象角色,则必须修改委托以显示正确的对象 属性。 如果您想使用 ListView 的部分功能,也需要角色。

就像@derm 说的,它对 QSortFilterProxyModel 也很有用(无耻的插件:如果你的模型有角色,用我的 SortFilterProxyModel library 过滤或排序它非常容易)。

您提到了可重用性和必须重新实现的东西。这是一个很好的观点,但是拥有一个基于 QObject 属性的角色的通用模型是完全可行的。 事实上,它已经完成,并且可以在此处获得非常许可的许可证:Thomas Boutroue's QQmlObjectListModel。在 C++ 中,它具有与 QList 相同的 API,但它公开了 QML 可用的 QAbstractListModel。 角色基于对象的属性,当发出通知信号时,它会发出相应的 dataChanged 信号。 insertRows 和好友也会自动处理。

话虽如此,我认为制作具有单一对象角色的模型没有多大意义。如果你想要一个带有 rowsInserted/rowRemoved 信号的合适模型(你应该,除非你只有一个静态模型,在这种情况下 QVariantListQObjectList 就足够了),无论如何,当您可以使用 QQmlObjectListModel 并完成它时,您必须自己实现它。