简体   繁体   English

Delphi 添加项目到 ComboBox 速度

[英]Delphi Adding Items to ComboBox Speed

I have a fairly complex and large application that hands loads and loads of data.我有一个相当复杂且大型的应用程序,它处理大量数据。 Is there a speedy way to add items to ComboBox that doesn't take so long?有没有一种快速的方法可以快速地将项目添加到 ComboBox 不需要这么长时间? On my P3 3.2ghz, the following snippet takes just under a second to add around 32,000 items.在我的 P3 3.2ghz 上,以下代码片段只需不到一秒的时间就可以添加大约 32,000 个项目。 (MasterCIList is a StringList with strings typically 20 - 30 bytes long). (MasterCIList 是一个字符串列表,字符串长度通常为 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;

Drilling down into the VCL, it appears that in TComboBoxStrings.Add , there is a call to深入到 VCL 中,似乎在TComboBoxStrings.Add中有一个调用

Result := SendMessage(ComboBox.Handle, CB_ADDSTRING, 0, Longint(PChar(S)));

I'm guessing this is really taking up time (okay, I know it is).我猜这真的很耗时(好吧,我知道是这样)。 Is there another way to populate the Items that is speedier?是否有另一种方法可以更快地填充项目? Any high-speed combo boxes available?有可用的高速组合框吗? I have the TMS components but they seem to be extensions of TComboBox.我有 TMS 组件,但它们似乎是 TComboBox 的扩展。

For instance, I have the PlusMemo which seems to be a total rewrite of a TMemo.例如,我有 PlusMemo,它似乎是对 TMemo 的完全重写。 I can easily add a million line in a second to a PlusMemo.我可以轻松地在一秒钟内向 PlusMemo 添加一百万行。 A TMemo, I don't think so. TMemo,我不这么认为。

Thank you so much for your time!非常感谢您的参与!

Sorry if I'm a nuisance, but I doubt a TComboBox with 32,000 items is even remotely ''usable'' --- I'd say there's a reason why it's slow: it was never meant to do this:)对不起,如果我很讨厌,但我怀疑一个包含 32,000 个项目的 TComboBox 甚至远程''可用'' --- 我会说它很慢是有原因的:它从来没有打算这样做:)

Would there be a possibility to filter the data, and only load a subset?是否有可能过滤数据,只加载一个子集? To be more concrete, in one particular database application I've been working on, the user can search for a person.更具体地说,在我一直在研究的一个特定数据库应用程序中,用户可以搜索一个人。 We let the user type at least 3 or 4 characters of the name, and only then begin to return results in a listbox.我们让用户输入至少 3 或 4 个字符的名称,然后才开始在列表框中返回结果。 This has greatly increased usability of the search form, also greatly speeding up the whole process.这大大提高了搜索表单的可用性,也大大加快了整个过程。

Would you be able to follow a similar approach?你能遵循类似的方法吗?

Or, on a completely different take, perhaps you could take a look at the VirtualTreeView component --- either for direct use, or for inspiration.或者,以完全不同的方式,也许您可以看一下VirtualTreeView组件 --- 直接使用或获得灵感。

I agree that 32K items is a ridiculous amount to have in a combobox... That being said, you might try adding the items to a TStringList first and then use a combination of Begin/EndUpdate and AddStrings:我同意在 combobox 中拥有 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;

The code compiles, but I didn't test it further than that;代码可以编译,但我没有进一步测试它; I've never felt the need to add more than a few dozen items to a combobox or listbox.我从来没有觉得需要向 combobox 或列表框添加几十个项目。 If any more items might be needed than that, I find a way to filter before populating the list so there are fewer items.如果可能需要更多的项目,我会在填充列表之前找到一种过滤方法,这样项目就会更少。

Just out of curiosity, how do you expect a user to sort through that many items to make a decision?只是出于好奇,您希望用户如何对这么多项目进行分类来做出决定?

var
  Buffer: TStringList;
begin
  Buffer := TStringList.Create;

  try
    // --> Add items to Buffer here <--

    ComboBox.Items := Buffer;
  finally
    FreeAndNil(Buffer);
  end;
end;

This is the fastest way we've found to update a visual control.这是我们发现更新视觉控件的最快方法。

The VCL does BeginUpdate, Clear, and EndUpdate internally. VCL 在内部执行 BeginUpdate、Clear 和 EndUpdate。

If you don't believe me, profile it.如果您不相信我,请简要介绍一下。

use backgroundworker for adding MasterCIList items.after complete adding items use only AddStrings.使用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;

Maybe you can try this?也许你可以试试这个?

"Speeding up adding items to a combobox or listbox" http://blogs.msdn.com/b/oldnewthing/archive/2004/06/10/152612.aspx “加快向 combobox 或列表框添加项目” http://blogs.msdn.com/b/oldnewthing/archive/2004/06/10/152612.aspx

perhaps cmb.Items.Assign(myStringList) will help.也许 cmb.Items.Assign(myStringList) 会有所帮助。

here's a wild idea: i haven't tried it but you might check to see if there's a way to virtually load the combobox by setting the number of items and then owner drawing.这是一个疯狂的想法:我还没有尝试过,但您可以检查是否有办法通过设置项目数量然后所有者绘图来虚拟加载 combobox。 please pardon this crazy idea but i think i've heard of this being available somehow.请原谅这个疯狂的想法,但我想我听说过这可以通过某种方式获得。 irrelevant: this is how it's done in Palm OS...where the faster way to load the combobox is to not load it all... ;-)无关:这就是它在 Palm OS 中的完成方式……加载 combobox 的更快方法是不加载所有内容……;-)

Not an answer, but why on earth would you want 32,000 items in a combo box?不是一个答案,但你到底为什么要在一个组合框中包含 32,000 个项目? That is a terrible way to store that much data.这是存储这么多数据的糟糕方式。

i agree;我同意; it's a bad practice...这是一个不好的做法...

It's me again.又是我。 I'm adding 32,000 items cause I need to.我要添加 32,000 个项目,因为我需要。 That's one of many controls in my application that has "lots" of items.这是我的应用程序中具有“大量”项目的众多控件之一。 I need to have that many items.我需要有那么多东西。 It works just fine looking things up.它工作得很好。 Perfectly in fact.事实上完美。 I'm just trying to optimize things.我只是想优化一些东西。 The users find things just fine since they are in a certain logical order.用户发现事情很好,因为它们是按照一定的逻辑顺序排列的。

Everything I've seem so far with Assign and AddStrings is that they eventually end up in Add with the SendMessage call.到目前为止,我对 Assign 和 AddStrings 的看法是,它们最终会通过 SendMessage 调用添加到 Add 中。 So I'll keep looking.所以我会继续寻找。

Thanks for the feedback.感谢您的反馈。

I implement this in a different manner.我以不同的方式实现这一点。 First i removed the combobox control and take textbox control and assign it autocomplete to custom source where the custom source string collection is 32k items.I get the selected value from a new query on controls validation.首先,我删除了 combobox 控件并获取文本框控件并将其自动完成分配给自定义源字符串集合为32k项的自定义源。我从控件验证的新查询中获取所选值。

So it can replace combobox functionality.因此它可以替代 combobox 功能。 Mostly about 32k items people dont scroll but they keep entering key strokes and is catched by our custom auto complete source..大多数人不滚动大约32k项,但他们不断输入击键,并被我们的自定义自动完成源捕获。

Perhaps you can use a database engine in the back-end and use a data aware component.也许您可以在后端使用数据库引擎并使用数据感知组件。 Then the things will be much more quicker and usable.然后事情会变得更快更有用。 Perhaps if you'll try to describe what do you try to accomplish we'll help you further.也许如果您尝试描述您要完成的工作,我们将进一步帮助您。 In any case, your UI design is, let's say, odd .无论如何,你的 UI 设计是奇怪的。 And for this perhaps the Embarcadero forums will help you better.为此, Embarcadero 论坛可能会为您提供更好的帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM