我有一个相当复杂的大型应用程序,可以处理数据的负载和负载。是否有一种快速的方法来向ComboBox添加不需要这么长时间的项目?在我的P3 3.2ghz上,以下片段只需不到一秒钟即可添加大约32,000个项目。 (MasterCIList是一个StringList,字符串通常为20-30个字节长)。
with LookupComboBox do
begin
Items.BeginUpdate;
Items.Clear;
for i := 0 to MasterCIList.Count - 1 do
Items.Add(MasterCIList[i]);
Items.EndUpdate;
end;
向下钻取到VCL,似乎在TComboBoxStrings.Add
中有一个调用
Result := SendMessage(ComboBox.Handle, CB_ADDSTRING, 0, Longint(PChar(S)));
我猜这真的占用了时间(好吧,我知道它是)。是否有另一种方法来填充更快速的项目?有没有高速组合盒?我有TMS组件,但它们似乎是TComboBox的扩展。
例如,我有PlusMemo似乎是对TMemo的完全重写。我可以在一秒钟内轻松地向PlusMemo添加一百万行。 TMemo,我不这么认为。
非常感谢您的时间!
答案 0 :(得分:17)
很抱歉,如果我是一个讨厌的人,但我怀疑一个拥有32,000项的TComboBox甚至可以远程“使用” - 我会说这是有原因的,因为它很慢:它从来没有打算这样做:)
是否有可能过滤数据,只加载一个子集?更具体地说,在我一直在研究的一个特定数据库应用程序中,用户可以搜索一个人。我们让用户输入至少3或4个字符的名称,然后才开始在列表框中返回结果。这大大提高了搜索表单的可用性,也极大地加快了整个过程。
您能否采用类似的方法?
或者,就完全不同的观点而言,也许您可以看一下VirtualTreeView组件---直接使用或灵感。
答案 1 :(得分:3)
我同意32K项目在组合框中是一个荒谬的数量...也就是说,您可以先尝试将项目添加到TStringList,然后使用Begin / EndUpdate和AddStrings的组合:
SL := TStringList.Create;
try
// Add your items to the stringlist
ComboBox.Items.BeginUpdate;
try
ComboBox.Items.AddStrings(YourStringList);
finally
ComboBox.Items.EndUpdate;
end;
finally
SL.Free;
end;
代码编译,但我没有进一步测试它;我从来没有觉得需要在组合框或列表框中添加几十个项目。如果可能需要更多项目,我会在填充列表之前找到一种过滤方式,以便减少项目。
出于好奇,您希望用户如何对这么多项目进行排序以做出决定?
答案 2 :(得分:2)
var
Buffer: TStringList;
begin
Buffer := TStringList.Create;
try
// --> Add items to Buffer here <--
ComboBox.Items := Buffer;
finally
FreeAndNil(Buffer);
end;
end;
这是我们发现更新视觉控件的最快方式。
VCL在内部执行BeginUpdate,Clear和EndUpdate。
如果你不相信我,请说出来。
答案 3 :(得分:1)
也许cmb.Items.Assign(myStringList)会有所帮助。
这是一个疯狂的想法:我没有尝试过,但你可能会检查是否有办法通过设置项目数量和所有者绘图来虚拟加载组合框。请原谅这个疯狂的想法,但我想我已经听说过这个可用的方式。无关紧要:这就是在Palm OS中完成的...加载组合框的更快方法是不加载所有......; - )
我同意;这是一个不好的做法...不是答案,但为什么在组合框中你想要32,000项?这是存储大量数据的可怕方法。
答案 4 :(得分:1)
这又是我。因为我需要,我正在添加32,000个项目。这是我的应用程序中具有“大量”项目的众多控件之一。我需要那么多东西。它的工作效果很好。完全实际上。我只是想优化一些事情。用户发现事情很好,因为它们处于某种逻辑顺序。
到目前为止我对Assign和AddStrings的所有看法都是他们最终使用SendMessage调用进入Add。所以我会继续寻找。
感谢您的反馈。
答案 5 :(得分:1)
使用backgroundworker添加MasterCIList项目。完成添加项目后,只使用AddStrings。
procedure TForm2.BackgroundWorker1Work(Worker: TBackgroundWorker);
var
I: Integer;
begin
MasterCIList.BeginUpdate;
try
MasterCIList.Capacity := 32 * 1024; // if derminate count of items
for I := 1 to 32 * 1024 do
begin
MasterCIList.Add(IntToStr(I));
{ if need progess }
if I mod 300 = 0 then
Worker.ReportProgress((I * 100) div MasterCIList.Capacity);
{ if need cancelable }
if (I mod 100 = 0) and Worker.CancellationPending then
Break;
end;
finally
MasterCIList.EndUpdate;
end;
end;
procedure TForm2.BackgroundWorker1WorkComplete(Worker: TBackgroundWorker;
Cancelled: Boolean);
begin
LookupComboBox.Items.AddStrings(MasterCIList );
// AddStrings use beginupdate..endupdate in itself
end;
答案 6 :(得分:1)
也许你可以试试这个?
“加快向组合框或列表框添加项目” http://blogs.msdn.com/b/oldnewthing/archive/2004/06/10/152612.aspx
答案 7 :(得分:0)
也许您可以在后端使用数据库引擎并使用数据感知组件。然后事情会更快和可用。也许如果你试着描述你想要完成什么,我们会进一步帮助你。无论如何,你的UI设计就是说,奇数。为此,Embarcadero forums可能会对你有所帮助。
答案 8 :(得分:0)
我以不同的方式实现这一点。首先,我删除了组合框控件并采用文本框控件并将其自动完成分配给自定义源,其中自定义源字符串集合为 32k 项目。我从控件验证的新查询中获取所选值。
因此它可以取代组合框功能。大多数关于 32k 项目的人不会滚动,但他们会继续输入击键,并被我们的自定义自动完整源代码所吸引..