Rem*_*eau 8 delphi vcl c++builder virtualtreeview
我有一个应用程序,从二进制日志文件加载记录,并在虚拟TListView中显示它们.文件中可能有数百万条记录,用户可以过滤显示,因此我不会一次加载内存中的所有记录,并且ListView项目索引不是一对一的关系.文件记录偏移(例如,列表项1可以是文件记录100).我使用ListView的OnDataHint事件来加载ListView实际感兴趣的项目的记录.当用户滚动时,OnDataHint指定的范围发生变化,允许我释放不在新范围内的记录,并分配新记录如所须.
这样工作正常,速度可以忍受,并且内存占用非常低.
我目前正在评估TVirtualStringTree作为TListView的替代品,主要是因为我想添加扩展/折叠跨越多行的记录的能力(我可以通过动态递增/递减项目计数来使用TListView来捏造它,但这不是像使用真正的树一样直接).
在大多数情况下,我已经能够移植TListView逻辑并让一切工作正常.我注意到TVirtualStringTree的虚拟范例有很大的不同.它没有与TListView相同的OnDataHint功能(我可以使用OnScroll事件伪造它,这允许我的内存缓冲逻辑继续工作),我可以使用OnInitializeNode事件将节点与分配的记录相关联.
但是,一旦树节点初始化,它就会看到它在树的生命周期内保持初始化状态.这对我不好.当用户滚动并从内存中删除记录时,我需要重置那些非可视节点,而不是完全从树中删除它们,或者丢失它们的展开/折叠状态.当用户将它们滚动回视图时,我可以重新分配记录并重新初始化节点.基本上,就虚拟化而言,我希望尽可能使TVirtualStringTree像TListView一样.
我已经看到TVirtualStringTree有一个ResetNode()方法,但每次尝试使用它时都会遇到各种错误.我一定是错了.我还想过将每个节点内的数据指针存储到我的记录缓冲区中,然后分配并释放内存,相应地更新这些指针.最终效果也不是很好.
更糟糕的是,我最大的测试日志文件中有大约500万条记录.如果我一次初始化具有那么多节点的TVirtualStringTree(当日志显示未经过滤时),那么树的内部开销就会占用高达260MB的内存(还没有分配任何记录).而使用TListView,加载相同的日志文件及其背后的所有内存逻辑,我可以使用几个MB.
有任何想法吗?
您可能不应该切换到 VST,除非您至少需要使用 VST 的一些标准列表框/列表视图所没有的优秀功能。但与扁平的项目列表相比,当然会有很大的内存开销。
TVirtualStringTree我认为仅使用能够扩展和折叠跨多行的项目并没有真正的好处。你写
主要是因为我想添加扩展/折叠跨多行记录的功能(我可以通过动态增加/减少项目计数来使用 TListView 来捏造它,但这并不像使用真正的树那么直接)。
但您可以轻松实现这一点,而无需更改项目计数。如果将Style列表框设置为lbOwnerDrawVariable并实现该OnMeasureItem事件,您可以根据需要调整高度以仅绘制第一行或所有行。手动绘制扩展三角形或树视图的小加号应该很容易。Windows API 函数DrawText()或DrawTextEx()可用于测量和绘制(可选自动换行)文本。
编辑:
抱歉,我完全忽略了您现在使用的是列表视图而不是列表框的事实。事实上,没有办法在列表视图中拥有不同高度的行,所以这是没有选择的。您仍然可以使用顶部带有标准标题控件的列表框,但这可能不支持您现在从列表视图功能中使用的所有内容,并且它本身可能比动态显示和隐藏列表视图行要完成更多甚至更多的工作。模拟折叠和扩展。
| 归档时间: |
|
| 查看次数: |
2791 次 |
| 最近记录: |