2009-03-20 8 views
6

Ho un'applicazione abbastanza complessa e di grandi dimensioni che consente di caricare carichi e carichi di dati. C'è un modo rapido per aggiungere elementi a ComboBox che non richiede così tanto tempo? Sul mio P3 3.2ghz, il seguente frammento di codice richiede poco meno di un secondo per aggiungere circa 32.000 articoli. (MasterCIList è una lista di stringhe con stringhe generalmente lunghe 20-30 byte).Delphi Aggiunta di elementi alla velocità di ComboBox

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

perforazione giù nella VCL, sembra che in TComboBoxStrings.Add, v'è una chiamata a risultati: = SendMessage (ComboBox.Handle, CB_ADDSTRING, 0, Longint (PChar (S)));

Immagino che stia davvero prendendo tempo (ok, lo so che lo è). C'è un altro modo per popolare gli Articoli che è più veloce? Sono disponibili scatole combox ad alta velocità? Ho i componenti TMS ma sembrano estensioni di TComboBox.

Ad esempio, ho il PlusMemo che sembra essere una riscrittura totale di un TMemo. Posso aggiungere facilmente un milione di righe in un secondo a PlusMemo. Un TMemo, io non la penso così.

Grazie mille per il vostro tempo!

+4

Non una risposta, ma perché mai vorresti 32.000 articoli in una casella combinata? Questo è un modo terribile per memorizzare tanti dati. –

risposta

1

forse cmb.Items.Assign (myStringList) aiuterà.

ecco un'idea selvaggia: non l'ho ancora provato ma è possibile controllare se c'è un modo per caricare virtualmente la casella combinata impostando il numero di elementi e quindi il disegno del proprietario. per favore perdona questa pazza idea, ma penso di averne sentito parlare in qualche modo. irrilevante: questo è il modo in cui è fatto in Palm OS ... dove il modo più veloce per caricare la combobox è di non caricarlo tutto ... ;-)

Non una risposta, ma perché mai vorresti 32.000 oggetti in una casella combinata? Questo è un modo terribile per memorizzare tanti dati.

sono d'accordo; è una cattiva pratica ...

17

Scusate se sono un seccatore, ma dubito che un TComboBox con 32.000 elementi sia anche solo lontanamente "utilizzabile" --- Direi che c'è un motivo per cui è lento: non è mai stato concepito per farlo :)

Esiste la possibilità di filtrare i dati e caricare solo un sottoinsieme? Per essere più concreto, in una particolare applicazione di database su cui ho lavorato, l'utente può cercare una persona. Lasciamo che l'utente digiti almeno 3 o 4 caratteri del nome e solo dopo inizi a restituire i risultati in una listbox. Ciò ha notevolmente aumentato l'usabilità del modulo di ricerca, accelerando inoltre notevolmente l'intero processo.

Sarebbe in grado di seguire un approccio simile?

Oppure, su una presa completamente diversa, forse si potrebbe dare un'occhiata al componente VirtualTreeView --- sia per uso diretto, sia per ispirazione.

+0

È un buon consiglio. Forse aggiungere le stringhe nel gestore OnDropDown, filtrato per iniziare con i caratteri che sono già stati immessi. In questo modo l'utente ha influenza sul ritardo. In ogni caso, una lista di ricerca con 32000 articoli è inutilizzabile, anche se popolata istantaneamente. – mghie

3

Sono d'accordo che 32K articoli è una quantità ridicola di avere in una casella combinata ... Detto questo, si potrebbe provare ad aggiungere gli elementi in una TStringList prima e poi utilizzare una combinazione di Begin/EndUpdate e 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; 

Il codice viene compilato, ma non l'ho verificato ulteriormente; Non ho mai sentito la necessità di aggiungere più di una dozzina di elementi a una casella combinata o a una casella di riepilogo. Se altri elementi potrebbero essere necessari, troverò un modo per filtrare prima di compilare l'elenco in modo che ci siano meno elementi.

Solo per curiosità, come ti aspetti che un utente possa scegliere tra tanti elementi per prendere una decisione?

1

Sono di nuovo io. Sto aggiungendo 32.000 articoli perché ne ho bisogno. Questo è uno dei molti controlli nella mia applicazione che ha "molti" articoli. Ho bisogno di avere tanti oggetti. Funziona bene guardando bene. Perfettamente in effetti. Sto solo cercando di ottimizzare le cose. Gli utenti trovano le cose bene perché sono in un certo ordine logico.

Tutto ciò che ho visto finora con Assign e AddStrings è che finiscono per finire in Aggiungi con la chiamata SendMessage. Quindi continuerò a cercare.

Grazie per il feedback.

+1

Innanzitutto, pubblicare una "risposta" come questa è errata. Modifica il tuo post originale. In secondo luogo, di nuovo, ho programmato per oltre 20 anni, ho vinto app per 15+, ho fatto alcune app straordinariamente complesse e non ho mai trovato la necessità di nemmeno 1K elementi in una combobox. Ma buona fortuna a te (e agli utenti della tua app). –

+0

D'accordo con Ken. Per essere chiari, è corretto pubblicare una risposta se è davvero una risposta alla tua domanda. Se hai un commento, modifica la tua domanda. – Argalatyr

0

Forse è possibile utilizzare un motore di database nel back-end e utilizzare un componente in grado di rilevare i dati. Quindi le cose saranno molto più veloci e utilizzabili. Forse se proverai a descrivere cosa proverai a fare, ti aiuteremo ulteriormente. In ogni caso, il tuo design dell'interfaccia utente è, diciamo, dispari. E per questo forse lo Embarcadero forums ti aiuterà meglio.

0

Lo implemento in un modo diverso. Per prima cosa ho rimosso il controllo della casella combinata e ho preso il controllo della casella di testo e l'ho assegnato automaticamente alla sorgente personalizzata in cui la raccolta della stringa di origine personalizzata è 32k elementi. Ricevo il valore selezionato da una nuova query sulla convalida dei controlli.

Quindi può sostituire la funzionalità di combobox. Per lo più circa 32k articoli gente non scorrere, ma continuano a entrare in combinazioni di tasti ed è pescati dalla nostra auto personalizzato sorgente completo ..

1

uso backgroundworker per l'aggiunta di MasterCIList items.after completi elementi che aggiungono utilizzare solo 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; 

Questo è il modo più veloce che abbiamo trovato per aggiornare un controllo visivo.

VCL esegue l'aggiornamento, la cancellazione e l'aggiornamento finale internamente.

Se non mi credi, profilalo.

Problemi correlati