SWT Table with over 200 columns doesn't render properly

eclipse, java, rcp, swt

Solution

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.

Problem

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

Original source