在不改变选择的情况下更新 QTreeView

Update of QTreeView without changing selection

我有一个模型,它通过某个 SQL 查询从数据库中的 table 检索数据,并在 QTreeView 中显示项目。特点是:

由于 children 随时添加到任何 parent,因此更新 QTreeView 时第一个愚蠢的方法是将其全部清除,然后再次追加所有行,形式为 parent 或 children,到 QTreeView。这是一个 0 阶的近似,效率确实低得可怕。特别是出现以下问题:

  1. 任何现有选择都已消失
  2. 显示其 children 的任何展开的 parent 已折叠(除非 ExpandAll 处于活动状态)
  3. 视图重置为显示第一行。

这个问题的最佳解决方案是什么?我的意思是,我将尝试的第一个解决方案不是清除 QTreeView,而是解析 table 中所有返回的行,并检查每个行是否存在 QTreeView 中的相应项目,并将其添加如果不。但我想知道是否有一个最棘手的解决方案来使用 QTreeView 将给定的 table 参与到数据库中(我知道 QTableView 存在这种情况,但树结构消失了)。

This thread 提到了一种通用方法,但这可能很快就会变得棘手,但我不确定如果基础模型不断变化(即 QModelIndex 变得无效),这将如何工作。

最坏的情况是您必须编写自己的机制来记住选择,然后再更新并重新应用它。

我假设您使用了一些 model/view 实现?您可以通过安全的选择处理来增强您的模型,以防上述示例对您不起作用。

我想这是自我回答的情况。

正如我推测的那样,在仔细分析了从数据库中检索的数据后,我不得不对检索代码执行以下操作"upgrades":

  • 我检索了两个标识符,以及我想在视图中显示的字段,一个用于分组行,一个用于排序项目分组
  • 我还从数据库中的table中检索了内部记录ID(一个递增的整数),以便在下一次只查询新记录检索。

在模型人口代码中,我添加了以下内容:

  • 我首先扫描可能属于模型中现有组的初始记录
  • 当我在扫描中到达模型中的最后一个组时,这意味着其余检索到的记录属于新组(请记住检索到的记录已排序,以便检索属于同一组的项目一起)
  • 然后开始创建组并向每个组添加项目,直到我们使用所有检索到的记录。

最后,很重要的一点:

  • 在模型中插入新项目前后使用 beginInsertRows()endInsertRows()
  • 捕获视图的排序状态(使用 sortIndicatorSection()sortIndicatorOrder())并在更新模型后重新应用此排序状态(使用 sortByColumn()

这样做会保留接收模型更新的 QTreeView 中的当前位置和选择,并添加视图中的项目并为用户透明地更新视图。