views:

835

answers:

3

How would you go about displaying huge amount of rows in SWT table? Huge is something above 20K rows, 20 columns. Don't ask me why I need to show that much data, it's not the point. The point is how to make it work as fast as possible so that end user won't get bored waiting. Each row displays an instance of some object, columns are its properties (some). I thought to use JFace content/label provider pattern, but afraid it will be even slower than hitting the table directly with the data. This is how it goes :

    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());
               ..... 
            }
       });

Drawing 20k records on my computer takes about 20 sec. The biggest performance problem I've seen in Windows are caused by incredible amount of native windowing messages sent by SWT when new table item created and populated with text. I've found great workaround for this - hide table before populating, and then show it when done. Just calling table.setVisible(false) before the loop and table.setVisible(true) after the loop does wonders - the speed goes up six-seven times!

I'd like to speed it up even more. What would you suggest ? Also, I wonder how this trick hiding the widget would work on non-windows implementations of SWT (aka Linux) ?

+1  A: 

You want to do lazy-loading on the table display. Basically, you keep all these objects offscreen in memory, then create only a handful of actual GUI table rows. As the user scrolls you re-render these rows with the objects at that scroll location.

See this article (EDIT: oops I meant this article) for a JFace example.

Benjamin Cox
Thanks for the hint, lazy drawing sounds like a good idea. Though I don't see how this snippet is different from mine, it runs over all items and draws it one by one...
Dima
Ooops! Wrong link, right site! Here's the one for an SWT table with a million rows: http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/CreateaSWTtablewith1000000items.htm. Just replace the "Add Items" button and re-implements its listener as a scroll listener that loads future items once you get near the end of the current set. Good luck!
Benjamin Cox
Great, this makes sense now, thanks !
Dima
+1  A: 

1 - use the setText(String[]) instead of setText(int, String) one call instead of several.

2 - use myTable.setRedraw(false) before and myTable.setRedraw(true) after the process to stop all redrawing opérations during loading data.

it's simpler and can improve performance !!

good luck.

on my side using this I load 2500 lines of 20 column in less than 300ms..... on a standard today PC.

YPE
+2  A: 

SWT can do that for you. When you use the SWT.VIRTUAL style flag, items are only created when scrolled into view. Here's how to do it:

  1. Create the table with style SWT.VIRTUAL
  2. Set the row count using Table#setItemCount()
  3. Add a SWT.SetData Listener that fills the TableItems on demand.

Here's a code snippet:

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();
}
ralfstx
This is exactly the solution, now filling up 100k rows takes almost zero time, quite amazing feature, thanks a bunch!
Dima