qt - 何时从 QAbstractItemModel 发出 dataChanged

标签 qt qtreeview qabstractitemmodel

在 Qt 中,我有一个模型子类 QAbstractItemModel - 它是在 QTreeView 中显示的树。

该模型支持各种形式的变化,它们都可以正常工作。相关的两个是:

1)少量相关行中的一些数据发生变化

2)可视化更改意味着大多数行应更改其格式 - 特别是它们具有背景突出显示的更改。他们的DisplayRole数据不变。

当前的设计以相同的方式处理这两种情况:对于有任何更改的每一行,模型都会发出 dataChanged(start_of_row_index,end_of_row_index) .我为改变的父行和改变的任何子行发出信号。

然而,当模型变大时,这在案例 2 中表现不佳:dataChanged 的数量非常大。发出信号。

我已经更改了代码,以便在案例 2 中模型发出 dataChanged仅适用于作为整个树的父级的(单)行。

这似乎仍然可以正常工作,但不符合我对模型职责的理解。但我怀疑我可能错了。

也许我误解了dataChanged信号?它实际上是否会导致 View 更新所有子项以及指定范围?或者我可以避免发出 dataChanged当它不是 DisplayRole那正在改变?

编辑了我到目前为止的进展

正如 Jan 指出的那样,我应该发出 dataChanged对于案例 2 中的大多数或所有行。

我的代码最初是通过发出 dataChanged 来实现的。对于每个更改的行,但这太昂贵了 - View 处理所有这些信号的时间太长。

一个可能的解决方案是聚合 dataChanged为更改行的任何连续 block 发出信号,但是当例如每隔一行发生更改时,这仍然不会很好地执行 - 它仍然会发出太多信号。

理想情况下,我只想告诉 View 将所有数据视为可能已更改(但所有索引仍然有效 - 布局未更改)。对于单个信号,这似乎是不可能的。

由于 QTreeView 的一个怪癖类,有可能(尽管根据规范不正确)只发出一个 dataChanged(tl,br ) 只要 tl != br .我有这个工作,它通过了我们的测试,但让我很紧张。

我现在已经确定了一个遍历树并发出单个 dataChanged(tl,br) 的版本。对于每个 parent (tl,br 跨越该 parent 的所有 child )。这符合模型/ View 协议(protocol),对于我们的模型,它通常将信号数量减少约 10 倍。

然而,这似乎并不理想。还有其他建议吗?

最佳答案

每当任何数据发生更改时,您都应该让您的 View 知道。这种“让知道”可以通过多种方式发生;发射dataChanged是索引结构没有改变时最常见的一种;其他是“严重”的,例如 modelResetlayoutChanged .巧合的是,即使没有 dataChanged,Qt 的某些 View 也能够获取更改。例如鼠标悬停,但你不应该依赖它。这是一个实现细节,也是一个可能发生变化的主题。

要回答你问题的最后一点,是的,dataChanged每当从 QAIM::data() 返回任何数据时都必须发出变化,即使它“只是”Qt::DisplayRole 之外的某个其他角色.

你在引用性能问题。硬性数字是多少——您实际上是否有任何可衡量的放缓,或者您是否过早地担心这可能会成为以后的问题?您是否知道可以使用 dataChanged 的两个参数这一事实?表示一个大的索引矩阵的变化?

编辑:

还有几件事要尝试:

  • 确保您的 View 不请求额外数据。例如,除非您设置 QTreeViewuniformRowHeights (IIRC), View 必须为每个 dataChanged 执行 O(n) 次调用信号,导致 O(n^2) 复杂度。那很糟。
  • 如果你真的确定没有办法解决这个问题,你可以通过结合 layoutAboutToBeChanged 来逃脱。 , updatePersistentIndexeslayoutChanged .由于您实际上并未更改索引的结构,因此这可能相当便宜。不过,前一点的优化机会还是值得把握的。
  • 关于qt - 何时从 QAbstractItemModel 发出 dataChanged,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16561974/

    相关文章:

    c++ - Access数据库-QODBC驱动程序对管理员执行授予

    c++ - 如何在 Qt creator 的 Qt Widgets 应用程序中播放本地视频?

    c++ - 如何使用 QModelIndex 访问 QTreeView 中的 childWidgets?

    qt - 如何突出显示 QTreeView 中的某些项目(无需继承)

    qt - 结合 QAbstractItemModels

    linux - 如何使用 Qt 5.9.1 修复 Qt Quick 应用程序中的撕裂?

    Qt:缺少 vtable 通常意味着第一个非内联虚拟成员函数没有定义

    python - 更改 QTreeView 中的某些数据

    c++ - 来自 jsonModel 的 QML 中的空 TreeView

    qt4 - 更改 QTreeView 中显示扩展箭头的列