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

时间:2018-07-23 08:39:09

标签: c++ sql qt qtreeview

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

  • 数据来自表,但具有底层树结构(某些行是父级,在其下面有作为子级的行)
  • 该树结构显示在QTreeView中
  • 孩子可以在QTreeView中选择(而不是父母)
  • 数据库中的表不断更新
  • 在更新中,可以将子级添加到任何现有的父级
  • 定期(使用QTimer)使用表的内容更新QTreeView

由于可以随时将子级添加到任何父级,因此更新QTreeView时的第一种愚蠢的方法是清除所有内容,然后以父级或子级的形式再次将所有行追加到QTreeView。这是一个0阶逼近,确实效率很低。特别是,出现以下问题:

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

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

2 个答案:

答案 0 :(得分:1)

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

最糟糕的情况是,您必须编写自己的机制来记住选择内容,然后再进行更新然后重新应用它。

我假设您使用某些model/view实现?如果上述示例不适合您,则可以通过安全的选择处理来增强模型。

答案 1 :(得分:0)

我想这是一个自我答案的情况。

我想像过,在仔细分析了从数据库中检索到的数据之后,我不得不对检索代码进行以下“升级”:

  • 我检索了两个标识符,以及要在视图中显示的字段,两个标识符,一个用于分组行,另一个用于将项目分组到组
  • 我还从数据库中的表中检索了内部记录ID (一个递增的整数),以便在下一次检索中仅询问新记录。

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

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

最后,这非常重要:

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

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