对 TListbox 进行排序——高点和低点

发布于 2024-08-04 13:39:42 字数 751 浏览 6 评论 0原文

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

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

现在,当前的问题是:

使用内置的 Sort 方法及其 Compare 回调函数几乎要花很长时间,比如很多分钟。

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

想了一会儿,我发现 QuickSort 正在移动所有这些字符串,这是没有必要的,因此我将代码更改为仅移动字符串的指针或索引,瞧,排序又快得多了,只需一秒即可对 43,000 件物品进行分类。大胜利,是吗?

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

不过一会儿,我发现我已经拥有 LB.TStrings 中的所有字符串,我只需要它们在我的 QuickSorted() 数组中进行洗牌即可。这应该是微不足道的,只需移动一些指针即可。

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

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

谢谢,

乔治

Okay, I have a TListBox that on occasion may be called upon to show 43,000 lines!

I know, this hardly ever makes any sense, but there it is.

Now here's the current problem:

Using the built-in Sort method, with its Compare callback function, takes nearly forever, like many minutes.

So I extract the strings out of the listbox into a plain old dynamic array of ShortStrintgs, do a QuickSort() on that, and that takes about three seconds. Whopee I think!

Doing a bit of thinking, I see that QuickSort is moving all those strings around, which there is no need for, so I cange the code to just move around pointers or indices to the strings, and voila, the sort is much faster again, takin under a second to sort 43,000 items. Big win, yes?

BUT, now if I do a LB.Items.Add() or LB.Items.Assign to move the sorted strings into the listbox, THAT takes like 30 seconds! Even with BEgin/EndUpdate happening. If I trace through the code I see a whole lot of stuff going on with delete() Insert() INsertObject() and Windows messages flying for no good reason.

A moment's though reveals that I HAVE all the strings in the LB.TStrings, I just need them shuffled around ala my QuickSorted() array. That should be trivial, just moving some pointers.

But I don't see any visible way to set the raw TStringList pointers. No, Exchange() is really really slow.

Any ideas how I can get to the TString string pointers? This should be trivial but I don't see it.

Thanks,

George

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一花一树开 2024-08-11 13:39:42

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

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

All those messages are actually flying around for a very good reason. There's no magic "display whatever's in the list" function. It has to take the contents of the list, build a tree from it, one item at a time, and display whatever part of that tree happens to fall within the ClientRect of the visual control. Your external string list technique sounds like the fastest thing you're going to get.

If you want better performance, try looking at a faster list box. I've heard that Virtual TreeView is incredibly fast at adding large batches of new items, though I can't really recommend it since I haven't used it and tested it myself. But you might want to take a look and see if it suits your needs better than your existing setup.

你不是我要的菜∠ 2024-08-11 13:39:42

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

请参阅 http://www.delphi3000.com/articles/article_3761.asp?SK=< /a>

Have you tried setting TListBox.Style to lbVirtual? Then the listbox asks you for the data in the OnData() event

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

趁年轻赶紧闹 2024-08-11 13:39:42

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

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

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

RedrawWindow(Application.Handle, nil, 0, [选项])

强制立即重绘所有内容。

One other method that you can use (I've used it successfully myself) to help keep things speedy is to stop the application from redrawing the controls, copying the list to a second TStringList, sort that TStringList, and copy back. The key to stopping the redraw is a command as such:

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

The first 0 tells the application to stop drawing to the window, so all of those messages get dropped immediately and the application can move much faster. When ready to redraw the screen, just swap the first 0 for a 1 and then call

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

to force an immediate redraw of everything.

海螺姑娘 2024-08-11 13:39:42

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

Try Virtual Treeview. I know it's not a listbox and it's a little bit complex than tlistbox but it can act like TListBox(or tlistview/ttreeview) and it's way faster than standart tlistbox/tlistview/ttreeview.(it can add 1000000 items in 125ms)

森林迷了鹿 2024-08-11 13:39:42

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

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

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

To disable updating the listbox control while reordering the strings, use BeginUpdate/EndUpdate:

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

Edit: You could also try virtual style (Style = lbVirtual, set Count property and handle OnData event).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文