使用 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
我有一个包含 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