2009-03-20 9 views
6

Ich habe eine ziemlich komplexe und große Anwendung, die Lasten und Lasten von Daten reicht. Gibt es eine schnelle Möglichkeit, Elemente zur ComboBox hinzuzufügen, die nicht so lange dauert? Auf meinem P3 3.2ghz dauert das folgende Snippet knapp eine Sekunde, um rund 32.000 Elemente hinzuzufügen. (MasterCIList ist eine StringList mit Strings, die typischerweise 20 - 30 Bytes lang sind).Delphi Hinzufügen von Elementen zu ComboBox Geschwindigkeit

with LookupComboBox do 
begin 
    Items.BeginUpdate; 
    Items.Clear; 
    for i := 0 to MasterCIList.Count - 1 do 
    Items.Add(MasterCIList[i]); 
    Items.EndUpdate; 
end; 

Bohren nach unten in die VCL, scheint es, dass in TComboBoxStrings.Add, gibt es einen Aufruf zu Ergebnis: = Sendmessage (ComboBox.Handle, CB_ADDSTRING, 0, Longint (PChar (S)));

Ich vermute, dies wirklich nimmt Zeit (okay, ich weiß, es ist). Gibt es eine andere Möglichkeit, die Items zu füllen, die schneller ist? Gibt es High-Speed-Combox-Boxen? Ich habe die TMS-Komponenten, aber sie scheinen Erweiterungen von TComboBox zu sein.

Zum Beispiel habe ich die PlusMemo, die insgesamt Umschreiben eines TMemo zu sein scheint. Ich kann problemlos eine Million Zeilen zu einem PlusMemo hinzufügen. Ein TMemo, das glaube ich nicht.

Vielen Dank für Ihre Zeit!

+4

Keine Antwort, aber warum in aller Welt möchten Sie 32.000 Artikel in einer Combo-Box? Das ist eine schreckliche Art, so viele Daten zu speichern. –

Antwort

1

vielleicht cmb.Items.Assign (myStringList) helfen.

hier ist eine wilde Idee: Ich habe nicht versucht, aber Sie könnten überprüfen, ob ein Weg, es gibt praktisch die Combobox zu laden, indem Sie die Anzahl der Elemente festlegen und dann Zeichnung Besitzer. Verzeihen Sie bitte diese verrückte Idee, aber ich denke, ich habe davon gehört, irgendwie verfügbar zu sein. irrelevant: So funktioniert es in Palm OS ... wo der schnellere Weg zum Laden der Combobox ist, nicht alles zu laden ... ;-)

Keine Antwort, aber warum in aller Welt willst du 32.000 Artikel in einer Combobox? Das ist eine schreckliche Art, so viele Daten zu speichern.

i zustimmen; es ist eine schlechte Praxis ...

17

Sorry, wenn ich ein Ärgernis bin, aber ich bezweifle, dass eine TComboBox mit 32.000 Elementen auch nur entfernt '' verwendbar '' --- Ich würde sagen, es gibt einen Grund, warum es langsam ist: es war nie dazu gedacht :)

Wäre es möglich, die Daten zu filtern und nur eine Teilmenge zu laden? Um konkreter zu sein: In einer bestimmten Datenbankanwendung, an der ich gearbeitet habe, kann der Benutzer nach einer Person suchen. Wir lassen den Benutzer mindestens 3 oder 4 Zeichen des Namens eingeben und erst dann beginnen, Ergebnisse in einer Listbox zurückzugeben. Dies hat die Verwendbarkeit des Suchformulars stark erhöht und den gesamten Prozess erheblich beschleunigt.

Würden Sie in der Lage, einen ähnlichen Ansatz zu folgen?

Oder, auf einer völlig anderen nehmen Sie möglicherweise einen Blick auf die VirtualTreeView Komponente --- entweder für den direkten Einsatz oder zur Inspiration.

+0

Es ist ein guter Tipp. Vielleicht fügen Sie die Strings im OnDropDown-Handler hinzu, gefiltert, um mit den Zeichen zu beginnen, die bereits eingegeben wurden. Auf diese Weise hat der Benutzer Einfluss auf die Verzögerung. In jedem Fall ist eine Suchliste mit 32000 Elementen unbrauchbar, selbst wenn sie sofort gefüllt wird. – mghie

3

Ich bin damit einverstanden, dass 32K Artikel eine lächerliche Menge in einer Combobox haben ... aber sagen, dass Sie könnten versuchen, zunächst die Elemente zu einem TStringList Hinzufügen und dann eine Kombination von Start/EndUpdate und AddStrings verwenden:

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; 

Der Code kompiliert, aber ich habe es nicht weiter getestet; Ich habe nie das Bedürfnis verspürt, mehr als ein paar Dutzend Artikel zu einer Combobox oder Listbox hinzuzufügen. Wenn möglicherweise noch mehr Elemente benötigt werden, finde ich eine Möglichkeit, vor dem Auffüllen der Liste zu filtern, damit weniger Elemente vorhanden sind.

Nur aus Neugier, wie Sie erwarten ein Benutzer durch, der viele Elemente zu sortieren, um eine Entscheidung zu treffen?

1

Ich bin es wieder. Ich füge 32.000 Artikel hinzu, weil ich es brauche. Das ist eine von vielen Steuerelementen in meiner Anwendung, die "viele" Elemente enthält. Ich muss so viele Gegenstände haben. Es funktioniert gut, Dinge zu suchen. Perfekt in der Tat. Ich versuche nur, die Dinge zu optimieren. Die Benutzer finden die Dinge gut, da sie in einer bestimmten logischen Reihenfolge sind.

Alles, was ich habe scheinen bisher mit Assign und AddStrings ist, dass sie schließlich mit dem Aufruf von Sendmessage in hinzufügen enden. Also werde ich weiter suchen.

Danke für die Rückmeldung.

+1

Erstens ist das Posten einer "Antwort" wie dieser falsch. Bearbeiten Sie Ihren ursprünglichen Beitrag. Zweitens programmiere ich seit mehr als 20 Jahren, habe Apps für 15+, Apps von extremer Komplexität und nie die Notwendigkeit für 1K-Artikel in einer Combobox gefunden. Aber viel Glück für Sie (und die Nutzer Ihrer App). –

+0

Stimmen Sie mit Ken überein. Um es klar zu sagen - es ist in Ordnung, eine Antwort zu posten, wenn es wirklich eine Antwort auf Ihre Frage ist. Wenn Sie einen Kommentar haben, dann bearbeiten Sie einfach Ihre Frage. – Argalatyr

0

Vielleicht können Sie einen Datenbank-Engine in dem Back-End verwenden und ein Datum Aware-Komponente verwenden. Dann werden die Dinge viel schneller und verwendbar sein. Wenn Sie versuchen zu beschreiben, was Sie versuchen zu erreichen, helfen wir Ihnen vielleicht weiter. In jedem Fall ist Ihr UI-Design, sagen wir mal, ungerade. Und vielleicht hilft Ihnen das Embarcadero forums besser.

0

Ich implementiere dies auf eine andere Art und Weise. Zuerst entfernte ich die Combobox Kontrolle und Textbox die Kontrolle übernehmen und sie zur automatischen Vervollständigung, um benutzerdefinierte Quelle zuweisen, wo die Zeichenfolge Sammlung benutzerdefinierte Quelle ist 32k items.I den ausgewählten Wert aus einer neuen Abfrage auf Kontrollen Validierung zu erhalten.

So kann es Combobox-Funktionalität ersetzen. Meist über 32k Artikel Menschen bewegen nicht aber sie halten Tastenanschläge Eingabe und wird durch unsere eigene Auto-Vervollständigen-Quelle catched ..

1

Verwendung backgroundworker für das Hinzufügen von MasterCIList items.after komplette Hinzufügen von Elementen verwenden nur 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; 
2
var 
    Buffer: TStringList; 
begin 
    Buffer := TStringList.Create; 

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

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

Dies ist der schnellste Weg, die wir gefunden haben eine visuelle Kontrolle zu aktualisieren.

Die VCL tut Beginupdate, klar und EndUpdate intern.

Wenn Sie mir nicht glauben, es profilieren.