动态树模型 (Qt)

Posted

技术标签:

【中文标题】动态树模型 (Qt)【英文标题】:Dynamic Tree Model (Qt) 【发布时间】:2014-02-11 18:41:37 【问题描述】:

我使用QAbstractItemModel 来表示树模型(最多包含几个猎物)。数据本身是动态的,任何时候节点都可能出现或消失,值(或其他角色)可能会发生变化。

对模型进行更改很容易;我想知道如何有效地发出信号以通知 QTreeView 的变化(它的大部分节点都折叠了)。

在任何给定时间,多个更改可能同时发生(行插入和/或删除)。

    使用beginInsertRows / endInsertRows / beginRemoveRows / endRemoveRows - 不应该有通知视图多个更改的方法吗? 就性能而言,最佳策略是什么?例如,从叶子开始直到每个节点的根 / 从下到上(相对于从上到下)/在插入之前删除 / 等等。 beginResetModel / endResetModel 的效率会不会低一些? 使用QStandardItemModel 有什么好处吗? (针对这种特定情况)。

【问题讨论】:

【参考方案1】:

    是的。通知每个人 disjoint 删除/添加的方法是发出多个信号。在大多数情况下,它会导致更多的开销来传递一些复杂的数据结构,而不仅仅是父索引和分隔行/列索引。

    您应该只通知删除/添加靠近根的项目。如果他们的父母随后消失,则通知孩子被带走是没有意义的。关于父母的通知意味着孩子显然已经不在了。

    这不仅关乎效率,还关乎状态。模型重置会重置视图状态。视图在收到重置后,只能假设它获得了一个全新的、不相关的模型——因此您会丢失选择、展开/折叠状态等。视图无法以任何其他方式面对重启。否则,视图需要保留自己的模型内容副本。

    由于模型重置意味着对所有项目进行重新布局,而且这可能是一件非常昂贵的事情,因此只有在总计超过 50% 的原始项目被更改(移除/替换)时,您才应该这样做/添加)。

    不,没有优势,除非您将数据存储为变体,否则使用QStandardItemModel 总是会导致更大的内存开销。如果它完全符合您的需求,那么它是一个很有意义的便利类。事实上,如果你不小心如何使用它,它会变得更糟。

    例如,如果您通过迭代深度优先并首先删除最远的孩子来删除一个项目,那么QStandardItemModel 无法预见未来——也就是说,您真的想删除所有这些的共同祖先孩子,并且会发出很多不必要的变化事件。您可以在自己的模型中正确处理它,或者如果您只是删除公共父级而不接触子级 - 因为它们也将被隐式删除。

【讨论】:

以上是关于动态树模型 (Qt)的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 lambda 表达式树中使用“动态”?

Razor 视图引擎:表达式树可能不包含动态操作

为树视图创建 Qt 模型

对于动态树 (Link-Cut-Tree, LCT) 的理解与总结

向 Qt 树模型添加一些自定义数据

Qt 模型的树视图和表视图