使用 ViewerComparator 排序 SWT Table 从不调用比较

Sort SWT Table with ViewerComparator never calls compare

我有一个包含 3 列的 SWT Table,应该由用户排序table。

我查看了 Whosebug 和其他站点,基于此我现在可以单击 header 列,显示 asc/desc 符号,但 table 中的所有数据被删除,并且永远不会调用 ViewerComparator 中的比较方法。

我的代码(Dienstleister 是一个简单的 POJO):

package testTableSort;

import java.util.ArrayList;
import java.util.Collection;

import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

import de.Dienstleister;
import de.MyComparator;

public class MyComposite extends Composite {

    public static void main(String[] args) {
        Display display = Display.getDefault();
        Shell shell = new Shell();
        MyComposite mycomp = new MyComposite(shell, SWT.NONE);
        shell.setLayout(new GridLayout(1, false));
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    private Table           table;
    private TableViewer     tableViewer;
    private MyComparator    comparator;

    public MyComposite(Composite parent, int style) {
        super(parent, style);
        setLayout(new FillLayout(SWT.HORIZONTAL | SWT.VERTICAL));

        Composite composite = new Composite(this, SWT.NONE);
        TableColumnLayout tcl_composite = new TableColumnLayout();
        composite.setLayout(tcl_composite);

        tableViewer = new TableViewer(composite, SWT.BORDER | SWT.FULL_SELECTION);
        table = tableViewer.getTable();
        table.setHeaderVisible(true);
        table.setLinesVisible(true);

        comparator = new MyComparator();
        tableViewer.setComparator(comparator);

        TableViewerColumn tvbNummer = new TableViewerColumn(tableViewer, SWT.NONE);
        TableColumn colNummer = tvbNummer.getColumn();
        tcl_composite.setColumnData(colNummer, new ColumnPixelData(100, true, true));
        colNummer.setText("Nummer");
        colNummer.addSelectionListener(getSelectionAdapter(colNummer, 0));

        TableViewerColumn tvcName = new TableViewerColumn(tableViewer, SWT.NONE);
        TableColumn colName = tvcName.getColumn();
        tcl_composite.setColumnData(colName, new ColumnPixelData(200, true, true));
        colName.setText("Name");
        colName.addSelectionListener(getSelectionAdapter(colName, 1));

        TableViewerColumn tvcBezeichnung = new TableViewerColumn(tableViewer, SWT.NONE);
        TableColumn colBezeichnung = tvcBezeichnung.getColumn();
        tcl_composite.setColumnData(colBezeichnung, new ColumnPixelData(200, true, true));
        colBezeichnung.setText("Bezeichnung");
        colBezeichnung.addSelectionListener(getSelectionAdapter(colBezeichnung, 2));

        setMyData(getMyData());
    }

    private Collection<Dienstleister> getMyData() {
        Collection<Dienstleister> coll = new ArrayList<Dienstleister>();

        Dienstleister d1 = new Dienstleister();
        d1.setName("Test");
        d1.setNummer(1);
        d1.setBeschreibung("Some text");
        Dienstleister d2 = new Dienstleister();
        d2.setName("ABC");
        d2.setNummer(2);
        d2.setBeschreibung("FGH");
        Dienstleister d3 = new Dienstleister();
        d3.setName("ZYX");
        d3.setNummer(3);
        d3.setBeschreibung("HGF");

        coll.add(d1);
        coll.add(d2);
        coll.add(d3);

        return coll;
    }

    public void setMyData(Collection<Dienstleister> p_data) {
        table.removeAll();
        for (Dienstleister entity : p_data) {
            TableItem item = new TableItem(table, SWT.NULL);
            item.setData(entity);
            item.setText(0, String.valueOf(entity.getNummer()));
            item.setText(1, entity.getName());
            item.setText(2, entity.getBeschreibung());
        }
    }

    private SelectionAdapter getSelectionAdapter(final TableColumn p_column, final int p_index) {
        SelectionAdapter selectionAdapter = new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                comparator.setColumn(p_index);
                int dir = comparator.getDirection();
                tableViewer.getTable().setSortDirection(dir);
                tableViewer.getTable().setSortColumn(p_column);
                tableViewer.refresh();
            }
        };
        return selectionAdapter;
    }
}

我的比较器class:

package de;

import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import de.Dienstleister;

public class MyComparator extends ViewerComparator {
    private int                 propertyIndex;
    private static final int    DESCENDING  = 1;
    private int                 direction   = DESCENDING;

    public MyComparator() {
        this.propertyIndex = 0;
        direction = DESCENDING;
    }

    public int getDirection() {
        return direction == 1 ? SWT.DOWN : SWT.UP;
    }

    public void setColumn(int column) {
        if (column == this.propertyIndex) {
            // Same column as last sort; toggle the direction
            direction = 1 - direction;
        } else {
            // New column; do an ascending sort
            this.propertyIndex = column;
            direction = DESCENDING;
        }
    }

    @Override
    public int compare(Viewer viewer, Object e1, Object e2) {
        Dienstleister p1 = (Dienstleister) e1;
        Dienstleister p2 = (Dienstleister) e2;

        int rc = 0;
        switch (propertyIndex) {
            case 0:
                rc = Integer.valueOf(p1.getNummer()).compareTo(p2.getNummer());
                break;
            case 1:
                rc = p1.getName().compareTo(p2.getName());
                break;
            default:
                rc = 0;
        }
        // If descending order, flip the direction
        if (direction == DESCENDING) {
            rc = -rc;
        }
        return rc;
    }
}

编辑: 根据greg_449提供的link修改了代码(http://www.vogella.com/tutorials/EclipseJFaceTable/article.html) 现在我得到一个异常 "Exception in thread "main" org.eclipse.core.runtime.AssertionFailedException: assertion failed: Unknown column layout data" 如果我不调用 createColumns 方法,我会在 table 中获得我的 pojo 的 toString() 输出。

public class MyComposite extends Composite {
    public static void main(String[] args) {
        Display display = Display.getDefault();
        Shell shell = new Shell();
        MyComposite mycomp = new MyComposite(shell, SWT.NONE);
        shell.setLayout(new GridLayout(1, false));
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    private TableViewer     tableViewer;

    public MyComposite(Composite parent, int style) {
        super(parent, style);
        setLayout(new FillLayout(SWT.HORIZONTAL | SWT.VERTICAL));

        Composite composite = new Composite(this, SWT.NONE);
        TableColumnLayout tcl_composite = new TableColumnLayout();
        composite.setLayout(tcl_composite);

        createViewer(composite);
    }

    private void createViewer(Composite p_composite) {
        tableViewer = new TableViewer(p_composite, SWT.BORDER | SWT.FULL_SELECTION);
        createColumns();
        final Table table = tableViewer.getTable();
        table.setHeaderVisible(true);
        table.setLinesVisible(true);

        tableViewer.setContentProvider(new ArrayContentProvider());
        tableViewer.setInput(getMyData());

        GridData gridData = new GridData();
        gridData.verticalAlignment = GridData.FILL;
        gridData.horizontalSpan = 1;
        gridData.grabExcessHorizontalSpace = true;
        gridData.grabExcessVerticalSpace = true;
        gridData.horizontalAlignment = GridData.FILL;
        tableViewer.getControl().setLayoutData(gridData);
    }

    private void createColumns() {
        TableViewerColumn tvbNummer = new TableViewerColumn(tableViewer, SWT.NONE);
        tvbNummer.getColumn().setText("Nummer");
        tvbNummer.getColumn().setWidth(100);
        tvbNummer.getColumn().setResizable(true);
        tvbNummer.getColumn().setMoveable(true);

        tvbNummer.setLabelProvider(new ColumnLabelProvider() {
            public String getText(Object element) {
                Dienstleister d = (Dienstleister) element;
                return d.getName();
            }
        });
    }

    private Collection<Dienstleister> getMyData() {
        Collection<Dienstleister> coll = new ArrayList<Dienstleister>();

        Dienstleister d1 = new Dienstleister();
        d1.setName("Test");
        d1.setNummer(1);
        d1.setBeschreibung("Some text");
        Dienstleister d2 = new Dienstleister();
        d2.setName("ABC");
        d2.setNummer(2);
        d2.setBeschreibung("FGH");
        Dienstleister d3 = new Dienstleister();
        d3.setName("ZYX");
        d3.setNummer(3);
        d3.setBeschreibung("HGF");

        coll.add(d1);
        coll.add(d2);
        coll.add(d3);

        return coll;
    }
}

要使用比较器,您还必须使用内容提供程序 (TableViewer.setContentProvider) 和标签提供程序或列标签提供程序。

自己创建 TableItems 意味着 TableViewer 根本无法工作。使用 TableViewer 时,您根本不应创建或访问 TableItem 对象 - TableViewer 会为您创建和管理这些对象。

关于 TableViewer 用法的更多详细信息 here