我正在开发一个GUI应用程序,它有一个TreeView(就像 用于显示大量项目的Win32 Regedit左侧面板 这是申请中最重要的部分。
+----------------------------------+-+
|[root] |#|
| +item |#|
| -item |#|
| +item | |
| -item | |
| item | |
| item | |
| ... | |
| +item | |
| +item | |
| ... | |
| +item | |
| +item | |
| ... | |
+----------------------------------+-+
目前这个应用程序是基于Qt构建的。我的ListView是 继承自QTreeView,我的ListModel继承自 化QAbstractItemModel。他们一起工作。做了一些 优化代码,效率要好得多 之前,但它仍然低于我除外。根据我的说法 测试,插入操作可以在几乎恒定的时间内完成, 所以这不是问题。问题在于绘制。画画时, 如果有新的,将调用QTreeView的doItemsLayout方法 项目。如果有更多项目需要更多时间。在 一开始,它可以忽略不计。如果有,我可以感受到GUI的延迟 插入时超过300K项目。 doItemsLayout方法 如果有1M项,则需要80+毫秒。经验 在GUI上并不好。另一个问题是QTreeView将耗尽 如果有超过32位Windows(或Wow64)的2GB用户空间 1M项目,流程刚刚崩溃。也许2GB不是很大 问题,因为我可以提供64位构建。
仔细思考后,我总结了要解决的问题 this:查找具有当前行索引的项目。TreeView的垂直滚动条为我们提供了一个索引 - 第一个 项目的索引。我们必须首先找到并绘制这个项目,然后简单地说 预先订购步行树以获得其余项目。只有几件事 在给定的时间需要,因为TreeView的高度是 有限。听起来不错,但事情并非那么简单。
开头只有一个根项目。新项目将是 经常在运行时插入。而TreeView的项目可能是 如果用户有子项(子项),则由用户展开或折叠。所以 项的行索引经常变化。 Qt的doItemsLayout很慢 因为它将所有项目插入到矢量容器中,并且 使用向量的下标索引作为项的行索引。什么时候 行索引将被更改,这个向量容器 变化。所以这将花费O(n)时间。
如何优化这是我的问题。我不是在谈论Qt,我 我在谈论一个常见的GUI问题。我可以在Qt或其他方面工作 GUI库,这不是问题。我的目标是支持更多 TreeView中的项目比1M(更多更好)。
是否有任何数据结构或算法可以提供帮助?有什么建议吗?
修改
如果您的建议是将项目分成几部分,而只是部分内容 树立刻可见,这件事已经完成。该 垂直滚动条和视口正是您所说的 关于。另外,我会提供过滤器,取景器等工具 对于用户,用户不需要处理所有项目 一旦。所以这不是一个大问题。
答案 0 :(得分:0)
这个问题去年已经解决了。
我的解决方案的关键是数据结构,我称之为“广泛” array",我不知道之前是否使用过这个数据结构。
一个常见的数组:
+-+-+-+-+-+-+-+--
|a|b|c|d|e|f|g|...
+-+-+-+-+-+-+-+--
A"广泛的阵列":
+---+---------+-+---+-----+---+---+--
| a | b |c| d | e | f | g |...
+---+---------+-+---+-----+---+---+--
这个想法是"宽阵列中的每个元素"有一个宽度 值,以便许多索引可以映射到一个元素,即许多 - 一对一的映射。元素的宽度可以动态更改 在log(N)时间内,插入或定位元素也会占用log(N) 时间。
"宽阵列的一个元素"被认为是TreeView的一个节点。一个 节点可以折叠或展开。折叠节点时,它 "宽阵列中的宽度"更改为1.当您展开时 节点,宽度在"宽数组"被改为总和 所有展开的子节点的宽度。基于此,定位一个 具有给定行索引的可见项非常快。
"广泛阵列"是2-3树的变种。