delphi – TVirtualStringTree – 重置非可视节点和内存消耗

前端之家收集整理的这篇文章主要介绍了delphi – TVirtualStringTree – 重置非可视节点和内存消耗前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个应用程序从二进制日志文件加载记录,并将其显示在虚拟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只能扩展和折叠跨越多行的项目的真正好处.你写

mainly because I want to add the ability to expand/collapse records that span multiple lines (I can fudge it with the TListView by incrementing/decrementing the item count dynamically,but this is not as straight forward as using a real tree).

但您可以轻松实现,而无需更改项目数.如果将列表框的样式设置为lbOwnerDrawVariable并实现OnMeasureItem事件,则可以根据需要调整高度以仅绘制第一行或所有行.手动绘制扩展器三角形或树形视图的小加号应该很容易. Windows API函数@L_301_1@或DrawTextEx()可用于测量和绘制(可选的自动换行)文本.

编辑:

对不起,我完全错过了你现在使用listview的事实,而不是列表框.实际上,在列表视图中没有办法让行具有不同的高度,所以这是没有选择的.您仍然可以在顶部使用带有标准标题控件的列表框,但是这可能不支持您现在使用的列表视图功能中的所有内容,并且它本身可能比动态显示和隐藏列表视图行更好或更多工作模拟折叠和扩展.

原文链接:https://www.f2er.com/delphi/102248.html

猜你在找的Delphi相关文章