在不改变选择的情况下更新 QTreeView
Update of QTreeView without changing selection
我有一个模型,它通过某个 SQL 查询从数据库中的 table 检索数据,并在 QTreeView 中显示项目。特点是:
- 数据来自 table,但具有底层树结构(有些行是 parent,它们下面的行是 children)
- 此树结构显示在 QTreeView 中
- children 在 QTreeView 中被选择table(parent 不是这样)
- 数据库中的table不断更新
- 在更新中,可以将 children 添加到任何现有的 parent
- 定期(使用 QTimer)QTreeView 使用 table
的内容更新
由于 children 随时添加到任何 parent,因此更新 QTreeView 时第一个愚蠢的方法是将其全部清除,然后再次追加所有行,形式为 parent 或 children,到 QTreeView。这是一个 0 阶的近似,效率确实低得可怕。特别是出现以下问题:
- 任何现有选择都已消失
- 显示其 children 的任何展开的 parent 已折叠(除非 ExpandAll 处于活动状态)
- 视图重置为显示第一行。
这个问题的最佳解决方案是什么?我的意思是,我将尝试的第一个解决方案不是清除 QTreeView,而是解析 table 中所有返回的行,并检查每个行是否存在 QTreeView 中的相应项目,并将其添加如果不。但我想知道是否有一个最棘手的解决方案来使用 QTreeView 将给定的 table 参与到数据库中(我知道 QTableView 存在这种情况,但树结构消失了)。
This thread 提到了一种通用方法,但这可能很快就会变得棘手,但我不确定如果基础模型不断变化(即 QModelIndex
变得无效),这将如何工作。
最坏的情况是您必须编写自己的机制来记住选择,然后再更新并重新应用它。
我假设您使用了一些 model/view 实现?您可以通过安全的选择处理来增强您的模型,以防上述示例对您不起作用。
我想这是自我回答的情况。
正如我推测的那样,在仔细分析了从数据库中检索的数据后,我不得不对检索代码执行以下操作"upgrades":
- 我检索了两个标识符,以及我想在视图中显示的字段,一个用于分组行,一个用于排序项目分组
- 我还从数据库中的table中检索了内部记录ID(一个递增的整数),以便在下一次只查询新记录检索。
在模型人口代码中,我添加了以下内容:
- 我首先扫描可能属于模型中现有组的初始记录
- 当我在扫描中到达模型中的最后一个组时,这意味着其余检索到的记录属于新组(请记住检索到的记录已排序,以便检索属于同一组的项目一起)
- 然后开始创建组并向每个组添加项目,直到我们使用所有检索到的记录。
最后,很重要的一点:
- 在模型中插入新项目前后使用
beginInsertRows()
和 endInsertRows()
- 捕获视图的排序状态(使用
sortIndicatorSection()
和 sortIndicatorOrder()
)并在更新模型后重新应用此排序状态(使用 sortByColumn()
)
这样做会保留接收模型更新的 QTreeView 中的当前位置和选择,并添加视图中的项目并为用户透明地更新视图。
我有一个模型,它通过某个 SQL 查询从数据库中的 table 检索数据,并在 QTreeView 中显示项目。特点是:
- 数据来自 table,但具有底层树结构(有些行是 parent,它们下面的行是 children)
- 此树结构显示在 QTreeView 中
- children 在 QTreeView 中被选择table(parent 不是这样)
- 数据库中的table不断更新
- 在更新中,可以将 children 添加到任何现有的 parent
- 定期(使用 QTimer)QTreeView 使用 table 的内容更新
由于 children 随时添加到任何 parent,因此更新 QTreeView 时第一个愚蠢的方法是将其全部清除,然后再次追加所有行,形式为 parent 或 children,到 QTreeView。这是一个 0 阶的近似,效率确实低得可怕。特别是出现以下问题:
- 任何现有选择都已消失
- 显示其 children 的任何展开的 parent 已折叠(除非 ExpandAll 处于活动状态)
- 视图重置为显示第一行。
这个问题的最佳解决方案是什么?我的意思是,我将尝试的第一个解决方案不是清除 QTreeView,而是解析 table 中所有返回的行,并检查每个行是否存在 QTreeView 中的相应项目,并将其添加如果不。但我想知道是否有一个最棘手的解决方案来使用 QTreeView 将给定的 table 参与到数据库中(我知道 QTableView 存在这种情况,但树结构消失了)。
This thread 提到了一种通用方法,但这可能很快就会变得棘手,但我不确定如果基础模型不断变化(即 QModelIndex
变得无效),这将如何工作。
最坏的情况是您必须编写自己的机制来记住选择,然后再更新并重新应用它。
我假设您使用了一些 model/view 实现?您可以通过安全的选择处理来增强您的模型,以防上述示例对您不起作用。
我想这是自我回答的情况。
正如我推测的那样,在仔细分析了从数据库中检索的数据后,我不得不对检索代码执行以下操作"upgrades":
- 我检索了两个标识符,以及我想在视图中显示的字段,一个用于分组行,一个用于排序项目分组
- 我还从数据库中的table中检索了内部记录ID(一个递增的整数),以便在下一次只查询新记录检索。
在模型人口代码中,我添加了以下内容:
- 我首先扫描可能属于模型中现有组的初始记录
- 当我在扫描中到达模型中的最后一个组时,这意味着其余检索到的记录属于新组(请记住检索到的记录已排序,以便检索属于同一组的项目一起)
- 然后开始创建组并向每个组添加项目,直到我们使用所有检索到的记录。
最后,很重要的一点:
- 在模型中插入新项目前后使用
beginInsertRows()
和endInsertRows()
- 捕获视图的排序状态(使用
sortIndicatorSection()
和sortIndicatorOrder()
)并在更新模型后重新应用此排序状态(使用sortByColumn()
)
这样做会保留接收模型更新的 QTreeView 中的当前位置和选择,并添加视图中的项目并为用户透明地更新视图。