QML 中包含对象的 QAbstractListModel 有什么缺点?

2022-01-19 00:00:00 qt qml c++ qabstractitemmodel

Qt 提供了将 C++ 模型与 QML 相结合的可能性并建议三个文档中的方法:

Qt offers the possibility to combine C++ models with QML and suggests three approaches in the docs:

  • QStringList
  • QObjectList
  • QAbstractItemModel

前两个使用起来非常简单,例如QObjectList:

The two former are extremely simple to use, e.g. QObjectList:

// in C++
QList<QObject*> dataList;
dataList.append(new DataObject("Item 1", "red"));

// in QML
ListView {
    model: dataList
    delegate: Text { text: name }
}

但它们都有一个强烈的警告:

but they both come with a strong caveat:

注意:视图无法知道QList 已更改.如果 QList 发生变化,则需要重新设置模型 [...]

Note: There is no way for the view to know that the contents of a QList has changed. If the QList changes, it is necessary to reset the model [...]

QAbstractItemModel 很难与对象一起使用,因为对象属性不直接公开,因此保持它们同步需要相当多的努力.

QAbstractItemModel is difficult to use with objects because the objects properties are not directly exposed and therefore keeping them in sync takes quite a bit of effort.

但是,可以将 QList 包装在 QAbstractItemModel 中并获得超级简单的模型.请参阅此处:实施 1、实施 2一个>

However, it is possible to wrap a QList in a QAbstractItemModel and obtain a super simple model. See here: Implementation 1, Implementation 2

Qt 没有原生实现这一点有什么原因吗?表现?内存管理问题?这似乎是一个明显的好主意,并且使用 ObjectModel 他们已经实现了类似的东西.

Is there a reason why Qt does not implement this natively? Performance? Memory management issues? It seems such an obviously good idea and with ObjectModel they already implement something similar.

推荐答案

使用 QObject 作为模型项的一个显着缺点是因为基类非常大,它有点像一个上帝对象"(这是一种反模式),其中包含很多你大部分时间并不真正需要的东西.因此,它在您可能拥有的任何模型数据之上都有大约 160 字节的开销".如果您有一个包含大量项目的大型模型,并且项目本身相对较小,这可能会出现问题.你最终会产生很多开销.

The one prominent downside of the usage of QObject as a model item is because the base class is pretty big, it is kind of a "god object" (which is an anti-pattern) that contains a whole lot of stuff you don't really need most of the time. As a result, it has about 160 bytes of "overhead" on top of any model data that you may have. Which may be problematic if you have a big model with lots of items, and the items themselves are relatively small. You end up with a lot of overhead.

一个 QObjectList 作为一个模型总是一个坏主意,除非你正在做一些完全微不足道的事情.由于它没有实现适当的接口来通知引用视图的更改,唯一的方法是强制更新,这将每次重绘整个模型,而不仅仅是更改.

A QObjectList as a model is always a bad idea, unless you are doing something entirely trivial. Since it doesn't implement the proper interface to notify referencing views of changes, the only way is to force an update, which will redraw the entire model each time rather than just the changes.

对item对象是什么没有要求,只要你正确地实现模型即可.

There is no requirement on what item objects are, as long as you implement the model properly.

第二个实现特别有用的原因有很多:

The second implementation in particularly useful for a number of reasons:

  • 您无需费心为每个使用场景实现具有固定角色的特定静态"模型
  • 您的模型项可以具有根本不同的属性,您不仅限于模型架构"
  • 由于您正在处理 QObjectQ_PROPERTY
  • ,因此您会自动收到 QML 中的绑定通知
  • 您可以在声明式中定义模型,甚至可以嵌套模型来创建树结构,这是 ListModel 无法做到的.
  • 您可以在纯 QML 中定义实际模型项,而无需一直重新编译,也就是快速原型设计,完成后,您可以简单地将对象移植到 C++
  • 同时,除了所有优点之外,该模型实际上比常规刚性"模型更易于实现和维护,角色查找更快,因为您基本上只有一个 对象 角色,无需任何查找,无需为角色实现数据更改信号等...简单易行
  • you don't need to bother with implementing a specific "static" model with fixed roles for each and every usage scenario
  • your model items can have fundamentally different properties, you are not limited to a model "schema"
  • you automatically get notifications for bindings in QML since you are dealing with QObject and Q_PROPERTY
  • you can define models in declarative, and you can even nest models to create tree structures, which you cannot do with ListModel.
  • you can define the actual model items in pure QML without having to recompile all the time, a.k.a rapid prototyping, and when done, you can simply port the objects to C++
  • at the same time, on top of all the advantages, the model is actually much simpler to implement and maintain than a regular "rigid" model, the role lookup is faster, since you essentially have a single object role and no lookup whatsoever, there is no need to implement data change signals for roles and so on... easy peasy

相关文章