【问题标题】:SWT Table with over 200 columns doesn't render properly超过 200 列的 SWT 表无法正确呈现
【发布时间】:2012-12-19 18:26:13
【问题描述】:

在我们的 Eclipse RCP 3.7 应用程序中,我们加载 Excel 文件并在表格中显示前 30 行,渲染的问题不在于行数,而在于列数,当它达到一定大小时表格似乎没有正确绘制,当您向右滚动时,单元格和标题会失去对齐,整个事情就会变得疯狂。

下面的独立类演示了这个问题,并遵循我在应用程序中使用的基本模式,以防出现问题。

关于如何解决这个问题的任何想法?

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


    }
}

【问题讨论】:

    标签: java eclipse swt rcp


    【解决方案1】:

    我猜TableViewer 在滚动时无法足够快地更新和呈现内容。

    您可以尝试查看 JFace 查看器的 SWT.VIRTUAL 样式和惰性内容提供程序。

    来自TableViewer的javadoc:

    从 3.1 开始,TableViewer 现在支持 SWT.VIRTUAL 标志。如果基础表是 SWT.VIRTUAL,则内容提供者可以实现 ILazyContentProvider 而不是 IStructuredContentProvider 。

    具有SWT.VIRTUAL 样式的TableViewer 可以使用ILazyContentProvider 按需创建和显示内容。有关使用虚拟查看器的一些副作用,请参阅 javadoc,例如对排序或过滤的限制。

    另请参阅此博客条目:JFace’s Viewers Performances

    由于标准 TableViewer 缓存行而不是列,因此 Nebula GridTableViewer 似乎更适合处理大量列的问题。它通知可见单元格,可以与LazyColumnLabelProvider 一起使用。

    有关使用星云GridTableViewer 的解决方案,请参阅这篇文章:JFace-Viewer and Eclipse Databinding with > 10.000 Objects

    【讨论】:

    • 也许我遗漏了一些东西,但这些东西都是基于渲染,大量的行。我只有 30 行,这没有问题,它无法处理大量列。
    • @GlenLamb 我更新了答案:GridTableViewer 似乎更适合您的问题。或者编写一个自己的带有缓存列的 TableViewer。
    • 哇,没有延迟提供或虚拟表,星云网格工作得更快更流畅,非常棒。唯一的问题是表格标题很难看,我设置了一个完整的“TableColumn”选择提供程序框架,我必须切换到“GridColumn”,但我正在尝试解决如何绘制网格标题。所以应该一切都好。
    【解决方案2】:

    这似乎是一个类似的问题。

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

    【讨论】:

    • 可以,但是没有解决办法。
    猜你喜欢
    • 2020-10-06
    • 2018-02-14
    • 1970-01-01
    • 2014-03-19
    • 2015-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多