1

好的,我有一个 TListBox,有时可能会被要求显示 43,000 行!

我知道,这几乎没有任何意义,但确实如此。

现在这是当前的问题:

使用内置的 Sort 方法和它的 Compare 回调函数,几乎需要很长时间,比如几分钟。

因此,我将列表框中的字符串提取到一个普通的、旧的 ShortStrings 动态数组中,对其执行 QuickSort(),这大约需要三秒钟。哇,我想!

稍微思考了一下,我看到 QuickSort 正在移动所有这些字符串,这是没有必要的,所以我可以让代码只移动指针或索引到字符串,瞧,排序又快了很多,花费不到一秒钟的时间对 43,000 件物品进行分类。大获全胜,是吗?

但是,现在如果我执行 LB.Items.Add() 或 LB.Items.Assign 将排序后的字符串移动到列表框中,则需要 30 秒!即使发生 BEgin/EndUpdate。如果我跟踪代码,我会看到 delete() Insert() INsertObject() 和 Windows 消息无缘无故飞来飞去。

片刻之后显示我在 LB.TStrings 中拥有所有字符串,我只需要在我的 QuickSorted() 数组周围随机排列它们。这应该是微不足道的,只是移动一些指针。

但我看不到任何设置原始 TStringList 指针的可见方法。不, Exchange() 真的很慢。

有什么想法可以获取 TString 字符串指针吗?这应该是微不足道的,但我没有看到。

谢谢,

乔治

4

5 回答 5

5

所有这些消息实际上都是有充分理由的。没有神奇的“显示列表中的任何内容”功能。它必须获取列表的内容,从中构建一棵树,一次一个项目,并显示该树的任何部分恰好落在可视控件的 ClientRect 内。您的外部字符串列表技术听起来像是您将获得的最快的东西。

如果您想要更好的性能,请尝试查看更快的列表框。我听说Virtual TreeView在添加大量新项目方面非常快,但我不能真正推荐它,因为我没有使用它并自己测试过。但是您可能想看看它是否比现有设置更适合您的需求。

于 2009-09-10T15:27:16.463 回答
4

您是否尝试过将 TListBox.Style 设置为 lbVirtual?然后列表框要求您提供 OnData() 事件中的数据

http://www.delphi3000.com/articles/article_3761.asp?SK=

于 2009-09-10T17:20:36.870 回答
1

尝试虚拟树视图。我知道它不是列表框,它比 tlistbox 有点复杂,但它可以像 TListBox(或 tlistview/ttreeview)一样工作,并且比标准 tlistbox/tlistview/ttreeview 快得多。(它可以在 125 毫秒内添加 1000000 个项目)

于 2009-09-10T15:49:58.127 回答
1

您可以使用的另一种方法(我自己已经成功使用过)来帮助保持快速,这是阻止应用程序重绘控件、将列表复制到第二个 TStringList、对该 TStringList 排序并复制回来。停止重绘的关键是这样的命令:

SendMessage(Application.Handle, WM_SETREDRAW, 0, 0);

第一个 0 告诉应用程序停止绘制到窗口,因此所有这些消息都会立即删除,并且应用程序可以更快地移动。当准备好重绘屏幕时,只需将第一个 0 换成 1,然后调用

RedrawWindow(Application.Handle, nil, 0, [Options])

强制立即重绘所有内容。

于 2009-09-10T15:36:36.047 回答
0

要在重新排序字符串时禁用更新列表框控件,请使用BeginUpdate/ EndUpdate

ListBox.Items.BeginUpdate;
try
  // your sorting here...
finally
  ListBox.Items.EndUpdate;
end;

编辑:您也可以尝试虚拟样式(Style = lbVirtual、设置Count属性和处理OnData事件)。

于 2009-09-10T15:23:42.480 回答