2009-11-13 15 views
11

Come si va a visualizzare una quantità enorme di righe nella tabella SWT? Enorme è qualcosa sopra le righe 20K, 20 colonne. Non chiedermi perché ho bisogno di mostrare tanti dati, non è questo il punto. Il punto è come farlo funzionare il più velocemente possibile in modo che l'utente non si annoi ad aspettare. Ogni riga visualizza un'istanza di qualche oggetto, le colonne sono le sue proprietà (alcune). Ho pensato di utilizzare il modello di provider di contenuti/etichette JFace, ma temo che sarà ancora più lento del colpire la tabella direttamente con i dati. Ecco come funziona:Popolamento di una tabella enorme nell'applicazione SWT/JFace RCP

Display.getDefault().asyncExec(new Runnable() { 
     public void run() { 
      List<MyObject> objects = model.getViewData(); 
      for(MyObject object: objects){ 
      TableItem item = new TableItem(table, SWT.NULL); 
      item.setImage(0, img1); 
      item.setBackground(color1); 
       item.setText(0, object.getProperty0()); 
       item.setText(1, object.getProperty1()); 
       item.setText(2, object.getProperty2()); 
       ..... 
      } 
     }); 

Disegno I record 20k sul computer richiedono circa 20 secondi. Il problema di prestazioni più grande che ho visto in Windows è causato dalla quantità incredibile di messaggi nativi di finestre inviati da SWT quando il nuovo elemento di tabella viene creato e popolato con testo. Ho trovato un ottimo rimedio per questo: nascondi la tabella prima di popolarla e poi mostrala quando hai finito. Basta chiamare table.setVisible (false) prima del ciclo e table.setVisible (true) dopo che il loop fa miracoli - la velocità aumenta di sei-sette volte!

Vorrei accelerarlo ancora di più. Cosa suggeriresti? Inoltre, mi chiedo come questo trucco che nasconde il widget possa funzionare su implementazioni non Windows di SWT (ovvero Linux)?

risposta

19

SWT può farlo per voi. Quando si utilizza il flag di stile SWT.VIRTUAL, gli elementi vengono creati solo quando si scorre nella vista. Ecco come fare:

  1. creare la tabella con stile SWT.VIRTUAL
  2. Impostare il conteggio delle righe utilizzando la tabella # setItemCount()
  3. aggiungere un listener SWT.SetData che riempie le TableItems su richiesta.

Ecco un frammento di codice:

public static void main(String[] args) { 
    Display display = new Display(); 
    Shell shell = new Shell(display); 
    shell.setLayout(new FillLayout()); 
    final Table table = new Table(shell, SWT.VIRTUAL); 
    table.setItemCount(10000); 
    table.addListener(SWT.SetData, new Listener() { 
     public void handleEvent(Event event) { 
      TableItem item = (TableItem)event.item; 
      item.setText("Item " + table.indexOf(item)); 
     } 
    }); 
    shell.setSize(300, 500); 
    shell.open(); 
    while(!shell.isDisposed()) { 
     if(!display.readAndDispatch()) { 
      display.sleep(); 
     } 
    } 
    display.dispose(); 
} 
+0

Questa è esattamente la soluzione, ora riempire 100k righe richiede quasi zero tempo, caratteristica davvero sorprendente, grazie mille! – Dima

+0

@ralfstx Puoi dirmi come posso filtrare una tabella come questa? –

+0

@AdamArold Puoi dare un'occhiata a 'DeferredContentProvider' per questo (vedi ad esempio questo [tutorial] (http://waynebeaton.wordpress.com/2008/01/16/deferredcontentprovider-my-new-favourite-thing/)) . Ma dovresti sapere che potrebbero esserci dei problemi con l'aggiornamento durante lo scorrimento: https://bugs.eclipse.org/bugs/show_bug.cgi?id=146799 – hnn

2

Si desidera eseguire il caricamento pigro sul display del tavolo. Fondamentalmente, si conservano tutti questi oggetti fuori dallo schermo in memoria, quindi si creano solo una manciata di righe effettive della tabella GUI. Mentre l'utente scorre, ri-renderizza queste righe con gli oggetti in quella posizione di scorrimento.

Vedi this article (EDIT: oops volevo dire this article) per un esempio di JFace.

+0

Grazie per il suggerimento, disegno pigro suona come una buona idea. Anche se non vedo come questo frammento di codice sia diverso dal mio, viene eseguito su tutti gli elementi e lo disegna uno ad uno ... – Dima

+0

Ooops! Link sbagliato, sito giusto! Ecco quello per una tabella SWT con un milione di righe: http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/CreateaSWTtablewith1000000items.htm.Sostituisci semplicemente il pulsante "Aggiungi elementi" e reimplementa il suo listener come un listener di scorrimento che carica gli articoli futuri una volta raggiunta la fine del set corrente. In bocca al lupo! –

+0

Grande, questo ha senso ora, grazie! – Dima

2

1 - utilizzare setText (String []) invece di setText (int, String) una chiamata anziché più.

2 - utilizzare myTable.setRedraw (false) before e myTable.setRedraw (true) dopo il processo per interrompere tutte le operazioni di ridisegno durante il caricamento dei dati.

è più semplice e può migliorare le prestazioni !!

buona fortuna.

da parte mia con questo carico 2500 linee di 20 colonne in meno di 300 ms ..... su un PC standard oggi.

Problemi correlati