2010-11-20 14 views
8

C'è una listview con diversi campi in delphi. Un thread controlla e aggiunge elementi a listview. Se c'è la stessa didascalia, verrà aggiunto un intero nel sottotitolo di questa didascalia. Quando il numero di elementi è inferiore a 2000, la prestazione è OK. Quando il controllo e l'aggiunta di voci e articoli contano più di circa 2000, le prestazioni sono scadenti. Quando gli elementi contano è maggiore di 20.000, la prestazione può essere descritta come estremamente lenta. C'è un modo per leggere velocemente e scrivere in listview quando gli articoli possono raggiungere 50.000 o 100.000?Come leggere velocemente e scrivere in listview in delphi?

Grazie mille in anticipo

Modifica:

Abbiamo letto tutte le vostre risposte e ringrazio tutti per il vostro aiuto.

risposta

9

Hai solo bisogno di utilizzare il tuo elenco in modalità "virtuale".

  1. Inserisci un TListBox nel modulo;
  2. Impostare la proprietà Style su lbVirtual.
  3. Impostare la proprietà Count sul numero di elementi dell'elenco.
  4. Quindi utilizzare il gestore OnData per fornire il testo da visualizzare su richiesta:

Come in questo codice (sostituisce con alcuni dati da database o un TStringList o tali):

procedure TForm1.ListBox1Data(Control: TWinControl; Index: Integer; 
    var Data: String); 
begin 
    Data := Format('Item %d',[Index+1]); // set the text to be displayed 
end; 

È possibile personalizzare ulteriormente il disegno utilizzando lo stile lbVirtualOwnerDraw ed è necessario disegnare gli elementi utilizzando un gestore di eventi OnDrawItem. C'è un codice di esempio nella documentazione di Delphi (almeno in Delphi 7). ;)

In modalità virtuale, è possibile visualizzare 50000 o 100000 articoli in modo istantaneo.

Per memorizzare il testo, utilizzare una buona vecchia TStringList sarà più veloce del metodo Items di TListBox, poiché questa proprietà Items [] dovrà comunicare con Windows con messaggi GDI "lenti" per ciascun elemento, mentre una TStringList conserverà il testo nell'heap Delphi, che di solito è molto più veloce.

+0

Grazie mille. – Dylan

6

È possibile chiamare BeginUpdate e EndUpdate in ListView per migliorare le prestazioni, impedendo al listview di ridisegnarsi durante l'aggiornamento. Ma questo probabilmente non ti darà la spinta che desideri. Inoltre, è necessario sapere che l'accesso ai controlli VCL direttamente da un thread non è sicuro se non sincronizzato.

Penso che sarebbe meglio saltare la listview e scegliere un controllo di terze parti come Virtual Tree View che è allo stesso tempo ottimo e gratuito. :)

+0

Ho esaminato rapidamente il componente Virtual Tree View. Quanto è "difficile" inserirlo in una applicazione utilizzando diversi controller e accessi TListView e TTreeView standard e funziona sulle colonne e sui nodi dell'albero dappertutto nel codice? Stiamo parlando di riscrittura completa di quelle parti? In caso affermativo, quanta differenza nel guadagno di velocità sarebbe semplicemente limitarsi a TTreeView e TListView bu cambiarli per funzionare come quelli virtuali? – inquam

+0

Onestamente non conosco la differenza di velocità. Penso che un TListView virtuale potrebbe essere abbastanza veloce, ma non l'ho usato in questo modo, quindi non posso darti un confronto adeguato. – GolezTrol

10

Il controllo TListView di Delphi è un wrapper attorno al componente di visualizzazione elenco di Windows. Nella sua modalità operativa predefinita, le copie dei dati della lista vengono trasferite dalla tua app al controllo di Windows e questo è lento.

L'alternativa a questo è nota come visualizzazione elenco virtuale nella terminologia di Windows. La tua app non trasmette i dati al controllo di Windows. Invece, quando il controllo deve visualizzare i dati, chiede alla tua app solo i dati necessari.

Il controllo TListView di Delphi espone le visualizzazioni di elenchi virtuali utilizzando la proprietà OwnerData. Dovrai riscrivere un po 'il codice della tua lista, ma è davvero l'unica soluzione.

+2

volevo anche suggerire che doveva passare alla modalità virtuale della listview. Personalmente utilizziamo il Virtual TreeView di cui ha parlato Golztrol. –

+1

La vista ad albero virtuale di Mike Lischke è davvero fantastica. C'è molto da dire però sull'utilizzo del componente di visualizzazione elenco se si dispone di un elenco piuttosto che di un albero perché consente di utilizzare il componente nativo per la piattaforma. Inoltre, la visualizzazione ad albero virtuale presenta una buona curva di apprendimento. –

+1

Purtroppo in questa modalità la listview non supporta GroupView ... – Tupel

2

Provare una Listview virtuale, utilizzando il gestore OnData.

I dati rimangono nella propria struttura dati, il listview chiama il gestore OnData per ottenere solo gli elementi di cui ha bisogno ogni volta che ne ha bisogno. ad esempio, estrai i dati particolari dalla tua struttura dati quando viene richiesto.

Altro lavoro è mantenere il valore di ItemCount della lista per il numero di elementi nell'elenco.

3

Diversi anni fa abbiamo rilevato che oltre a BeginUpdate/EndUpdate modifica ViewStyle di ListView a vsIcon prima di aggiungere grandi quantità di dati ad esso e di tornare a vsRepord dopo aver ottenuto prestazioni notevolmente migliorate. Era su Windows 98 e Windows 2000, se ricordo male, quindi non sono sicuro che sia ancora così.

3

BeginUpdate e EndUpdate sono un must assoluto durante l'aggiornamento degli articoli. Dalla tua descrizione sembra il tuo scorrere tra gli elementi alla ricerca di una didascalia specifica. Questo è lento e diventerà più evidente con grandi quantità di dati, ovviamente.

Poiché la ricerca di una didascalia corrispondente utilizza la funzione di visualizzazione degli elenchi FindCaption.

Fa una chiamata di Windows per cercare gli elementi ed è abbastanza veloce e semplice. Se lo trova, restituisce l'elemento e puoi fare riferimento ad esso per aggiornare il sottoelemento. In caso contrario, crea un nuovo elemento e continua con l'elaborazione.

Fintanto che il thread è sicuro e si dovrebbe essere in grado di vedere prestazioni decenti.

HTH.

+0

FindCaption IIRC porta a una chiamata API, ma potrei sbagliarmi. Non ho Delphi su questa macchina per essere sicuro al 100%. –

Problemi correlati