Link19
Link19

Reputation: 606

SWT Table with over 200 columns doesn't render properly

In our Eclipse RCP 3.7 application we load in Excel files and display the first 30 rows in a table, the problem with the rendering isn't in the rows but in the number of columns, when it gets to a certain size the table doesn't seem to draw properly, and when you scroll along to the right the cells and headers get out of alignment and the whole thing just goes crazy.

The stand alone class bellow demonstrates this problem, and follows the basic pattern I've used in my app in case that's where the problem is.

Any thoughts on how to solve this?

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;



public class Snippet {

    public static TableViewer viewer;

    public static void main( String[] args ) {
        Display display = new Display();
        Shell shell = new Shell( display );
        shell.setLayout( new FillLayout() );
       viewer = new TableViewer(shell, SWT.FULL_SELECTION | SWT.H_SCROLL
                | SWT.V_SCROLL);
        Table table = viewer.getTable();
        table.setLinesVisible(true);
        table.setHeaderVisible(true);

        viewer.setContentProvider(new ArrayContentProvider());
        createColumns(300);
        viewer.setInput(generateData(300, 30));
        for (TableColumn c : viewer.getTable().getColumns()) {
            c.pack();
        }


        shell.setSize( 300, 500 );
        shell.open();
        while( !shell.isDisposed() ) {
            if( !display.readAndDispatch() ) {
                display.sleep();
            }
        }
        display.dispose();
    }

    private static void createColumns(int columnCount) {

        for (int i = 0; i < columnCount; i++) {
            createTableViewerColumn(i);

        }
    }

    private static TableViewerColumn createTableViewerColumn(int colNum) {
        final TableViewerColumn viewerColumn = new TableViewerColumn(viewer,
                SWT.NONE);
        final TableColumn column = viewerColumn.getColumn();
        column.setText("Table Header " + colNum);
        column.setWidth(100);
        column.setResizable(true);
        column.setMoveable(false);
        viewerColumn.setLabelProvider(new Snippet.SampleDataTableCellProvider(colNum));
        return viewerColumn;
    }

    private static List<String[]> generateData(int cols, int rows) {
        ArrayList<String[]> result = new ArrayList<String[]>();
        for  (int y = 0; y < rows; y++) {
            String[] row = new String[cols];
            for  (int x = 0; x < cols; x++) {
                row[x] = "Big long string to test how long these columns can go before it all goes mental.";
            }
            result.add(row);
        }
        return result;
    }

    private static class SampleDataTableCellProvider extends StyledCellLabelProvider {

        private int colnumber;

        private SampleDataTableCellProvider(int colnumber) {
            this.colnumber = colnumber;
        }

        @Override
        public void update(ViewerCell cell) {

            String[] row = (String[]) cell.getElement();
            if (row.length > colnumber) {
                cell.setText(row[colnumber]);
            } else {
                cell.setText("");
            }

            super.update(cell);
        }


    }
}

Upvotes: 4

Views: 2011

Answers (2)

Modus Tollens
Modus Tollens

Reputation: 5123

I guess that the TableViewer can't update and render the content fast enough while scrolling.

You can try to take a look at the SWT.VIRTUAL style and lazy content providers for JFace viewers.

From the javadoc of TableViewer:

As of 3.1 the TableViewer now supports the SWT.VIRTUAL flag. If the underlying table is SWT.VIRTUAL, the content provider may implement ILazyContentProvider instead of IStructuredContentProvider .

A TableViewer with the SWT.VIRTUAL style can use an ILazyContentProvider to create and show content on demand. See the javadoc for some side effects of using virtual viewers, e.g. restrictions on sorting or filtering.

See also this Blog entry: JFace’s Viewers Performances.

Since the standard TableViewer caches rows and not columns, the Nebula GridTableViewer seems to be better suited for a problem dealing with a lot of columns. It informs about visible cells and can be used with a LazyColumnLabelProvider.

For a solution using the Nebula GridTableViewer see this article: JFace-Viewer and Eclipse Databinding with > 10.000 Objects.

Upvotes: 5

sambi reddy
sambi reddy

Reputation: 3085

This seems like a similar issue.

https://bugs.eclipse.org/bugs/show_bug.cgi?id=124965

Upvotes: -1

Related Questions