Populating huge table in SWT/JFace RCP application

10,355

Solution 1

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

Solution 2

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.

Solution 3

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.

Share:
10,355
Dima
Author by

Dima

Updated on June 17, 2022

Comments

  • Dima
    Dima almost 2 years

    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) ?

  • Dima
    Dima over 14 years
    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...
  • Benjamin Cox
    Benjamin Cox over 14 years
    Ooops! Wrong link, right site! Here's the one for an SWT table with a million rows: java2s.com/Code/Java/SWT-JFace-Eclipse/…. 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!
  • Dima
    Dima about 14 years
    This is exactly the solution, now filling up 100k rows takes almost zero time, quite amazing feature, thanks a bunch!
  • Adam Arold
    Adam Arold over 11 years
    @ralfstx Can you tel me how can I filter a Table like this?
  • hnn
    hnn about 10 years
    @AdamArold You can take a look at DeferredContentProvider for this (see e.g. this tutorial). But you should be aware that there might be some problems with refresh when scrolling: bugs.eclipse.org/bugs/show_bug.cgi?id=146799
  • user1168608
    user1168608 over 9 years
    @ralfstx I'm using JFace TableViewer's ContentProvider and LabelProvider to fill the data in rows and columns. Hence i can't follow the steps 2,3 that you have listed. So would the loading time improve if i use SWT.VIRTUAL on TableViewer alone?
  • ralfstx
    ralfstx over 9 years
    @user1168608 No, the idea of virtual tables is that you create items on demand. If you don't do so, the VIRTUAL flag won't buy you anything.