按多列对 JFace TableViewer 进行排序
Sort JFace TableViewer by Multiple Columns
我很确定我要问的是不可能的,但我在任何地方都找不到对这个问题的明确否定,所以这里是:
考虑以下工作示例:
public class TableViewerSorter {
private static final String DATA_COMPARATOR = "comparator";
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final TableViewer viewer = new TableViewer(shell, SWT.BORDER);
Table table = viewer.getTable();
table.setHeaderVisible(true);
viewer.setContentProvider(ArrayContentProvider.getInstance());
viewer.setSorter(new ViewerSorter() {
@Override
public int compare(Viewer v, Object e1, Object e2) {
TableColumn sortColumn = table.getSortColumn();
Comparator comparator = sortColumn == null ? null : (Comparator) sortColumn.getData(DATA_COMPARATOR);
if (comparator != null && table.getSortDirection() == SWT.UP) {
comparator = comparator.reversed();
}
return comparator == null ? 0 : comparator.compare(e1, e2);
}
});
createTableViewerColumn(viewer, "ID", v -> v.ordinal());
createTableViewerColumn(viewer, "Name", v -> v.getDisplayName());
createTableViewerColumn(viewer, "Fruit", v -> v.isFruit());
for (TableColumn column : table.getColumns()) {
column.addListener(SWT.Selection, e -> {
final Item sortColumn = table.getSortColumn();
int direction = table.getSortDirection();
if (column.equals(sortColumn)) {
direction = direction == SWT.UP ? SWT.DOWN : SWT.UP;
} else {
table.setSortColumn(column);
direction = SWT.UP;
}
table.setSortDirection(direction);
viewer.refresh();
});
}
viewer.setInput(Value.values());
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
private static <T extends Comparable<T>> TableViewerColumn createTableViewerColumn(TableViewer viewer, String name,
Function<Value, T> propertyFunction) {
TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
viewerColumn.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
return propertyFunction.apply((Value) element).toString();
}
});
TableColumn column = viewerColumn.getColumn();
column.setText(name);
column.setWidth(100);
column.setData(DATA_COMPARATOR, (Comparator<Value>) (v1, v2) -> propertyFunction.apply(v1).compareTo(propertyFunction.apply(v2)));
return viewerColumn;
}
static enum Value {
APPLE, BANANA, CABBAGE, DILL, EGGPLANT;
String getDisplayName() {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
boolean isFruit() {
return this != CABBAGE && this != DILL;
}
}
static class LabelProvider<T> extends ColumnLabelProvider {
private final Function<T, String> toStringFunction;
public LabelProvider(final Function<T, String> toStringFunction) {
this.toStringFunction = toStringFunction;
}
@Override
public String getText(final Object element) {
return element == null ? null : this.toStringFunction.apply((T) element);
}
}
}
我想要的是让用户单击第二列,然后单击第三列,然后按第三列对输入进行排序,当值相等时,按第二列排序。
当然我可以只将点击列的列表添加到 ViewerSorter
,或者(取决于排序算法)只使用最后排序的元素列表作为排序的基础而不是查看者的输入.
这是简单的部分。
困难的部分是如何向用户传达这个特定的 table 是按两列排序的。 API 似乎不支持用例,但我想确定:JFace table 是否可以按多列排序?如果可以,怎么做?
目前没有标准的方法来指示多个排序列。有一个长期存在的错误 133154 请求支持多个 setSortColumm
列,但什么也没做。
是的。 greg-449 是正确的,目前还没有标准实施。如果您真的很想知道它是如何工作的,我有一个解决方法,使用 TableColumn.setImage(image)
,set correct sort image on column 。维护 TableColumn.setData(key,value)
中的排序顺序和 Table.setData(key,value)
中的所有排序列,永远不要使用或设置 Table.setSortDirection(direction)
和 Table.setSortColumn().
我很确定我要问的是不可能的,但我在任何地方都找不到对这个问题的明确否定,所以这里是:
考虑以下工作示例:
public class TableViewerSorter {
private static final String DATA_COMPARATOR = "comparator";
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final TableViewer viewer = new TableViewer(shell, SWT.BORDER);
Table table = viewer.getTable();
table.setHeaderVisible(true);
viewer.setContentProvider(ArrayContentProvider.getInstance());
viewer.setSorter(new ViewerSorter() {
@Override
public int compare(Viewer v, Object e1, Object e2) {
TableColumn sortColumn = table.getSortColumn();
Comparator comparator = sortColumn == null ? null : (Comparator) sortColumn.getData(DATA_COMPARATOR);
if (comparator != null && table.getSortDirection() == SWT.UP) {
comparator = comparator.reversed();
}
return comparator == null ? 0 : comparator.compare(e1, e2);
}
});
createTableViewerColumn(viewer, "ID", v -> v.ordinal());
createTableViewerColumn(viewer, "Name", v -> v.getDisplayName());
createTableViewerColumn(viewer, "Fruit", v -> v.isFruit());
for (TableColumn column : table.getColumns()) {
column.addListener(SWT.Selection, e -> {
final Item sortColumn = table.getSortColumn();
int direction = table.getSortDirection();
if (column.equals(sortColumn)) {
direction = direction == SWT.UP ? SWT.DOWN : SWT.UP;
} else {
table.setSortColumn(column);
direction = SWT.UP;
}
table.setSortDirection(direction);
viewer.refresh();
});
}
viewer.setInput(Value.values());
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
private static <T extends Comparable<T>> TableViewerColumn createTableViewerColumn(TableViewer viewer, String name,
Function<Value, T> propertyFunction) {
TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
viewerColumn.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
return propertyFunction.apply((Value) element).toString();
}
});
TableColumn column = viewerColumn.getColumn();
column.setText(name);
column.setWidth(100);
column.setData(DATA_COMPARATOR, (Comparator<Value>) (v1, v2) -> propertyFunction.apply(v1).compareTo(propertyFunction.apply(v2)));
return viewerColumn;
}
static enum Value {
APPLE, BANANA, CABBAGE, DILL, EGGPLANT;
String getDisplayName() {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
boolean isFruit() {
return this != CABBAGE && this != DILL;
}
}
static class LabelProvider<T> extends ColumnLabelProvider {
private final Function<T, String> toStringFunction;
public LabelProvider(final Function<T, String> toStringFunction) {
this.toStringFunction = toStringFunction;
}
@Override
public String getText(final Object element) {
return element == null ? null : this.toStringFunction.apply((T) element);
}
}
}
我想要的是让用户单击第二列,然后单击第三列,然后按第三列对输入进行排序,当值相等时,按第二列排序。
当然我可以只将点击列的列表添加到 ViewerSorter
,或者(取决于排序算法)只使用最后排序的元素列表作为排序的基础而不是查看者的输入.
这是简单的部分。
困难的部分是如何向用户传达这个特定的 table 是按两列排序的。 API 似乎不支持用例,但我想确定:JFace table 是否可以按多列排序?如果可以,怎么做?
目前没有标准的方法来指示多个排序列。有一个长期存在的错误 133154 请求支持多个 setSortColumm
列,但什么也没做。
是的。 greg-449 是正确的,目前还没有标准实施。如果您真的很想知道它是如何工作的,我有一个解决方法,使用 TableColumn.setImage(image)
,set correct sort image on column 。维护 TableColumn.setData(key,value)
中的排序顺序和 Table.setData(key,value)
中的所有排序列,永远不要使用或设置 Table.setSortDirection(direction)
和 Table.setSortColumn().