我有一个与 TreeView 关联的 TableView。每次选择 TreeView 中的一个节点时,都会用不同的数据刷新 TableView。
我可以对 TableView 中的任何列进行排序,只需按下相应的列标题。这很好用。
但是:当我在树视图中选择不同的节点时,即使列标题继续显示为已排序。数据不是。
有没有一种方法可以在每次数据更改时以编程方式强制用户进行排序?
好的,我找到了方法。我将在这里总结一下,以防对其他人有用:
在更新 TableView 的内容之前,必须保存 sortcolum(如果有)和 sortType:
TableView rooms;
...
TableColumn sortcolumn = null;
SortType st = null;
if (rooms.getSortOrder().size()>0) {
sortcolumn = (TableColumn) rooms.getSortOrder().get(0);
st = sortcolumn.getSortType();
}
然后,在完成 TableView 中的数据更新后,您必须恢复丢失的排序列状态并执行排序。
if (sortcolumn!=null) {
rooms.getSortOrder().add(sortcolumn);
sortcolumn.setSortType(st);
sortcolumn.setSortable(true); // This performs a sort
}
我没有考虑排序中有多个列的可能性,但是使用这些信息很简单。
我遇到了同样的问题,发现在更新数据后,您只需在表格视图上调用函数 sort() :
TableView rooms;
...
// Update data of rooms
...
rooms.sort()
表格视图知道要排序的列,因此排序函数将按所需顺序对新数据进行排序。此功能仅在 Java 8 中可用。
如果您的 TableView 没有重新初始化,您还可以执行以下操作:
TableColumn<BundleRow, ?> sortOrder = rooms.getSortOrder().get(0);
rooms.getSortOrder().clear();
rooms.getSortOrder().add(sortOrder);
fornacif的示例有效,但如果有多个排序顺序,则无效(尝试按住 shift 单击第二列以创建辅助排序顺序)。
要对所有列进行重新排序,您需要执行以下操作:
List<TableColumn<Room, ?>> sortOrder = new ArrayList<>(roomTable.getSortOrder());
roomTable.getSortOrder().clear();
roomTable.getSortOrder().addAll(sortOrder);
如果您使用 TableView.setItems() 方法,它似乎会重置 TableView 的几个方面。将 TableView 中的 ObservableList 保留在原位,清除其内容,然后添加新项目。然后, TableView.sort() 仍然会知道哪些列之前已排序并且它将起作用。像这样:
tableView.getItems().clear();
tableView.getItems().addAll(newTableData);
tableView.sort();
Marco Jakob 的回答在大多数情况下都很好,但我发现我需要创建一个与表格排序顺序匹配的比较器以获得更大的灵活性。然后,您可以使用任何采用比较器进行排序、搜索等的方法。为了创建比较器,我从 apache 的 Common-Collections 扩展了ComparatorChain类,以便轻松地进行多列排序。它看起来像这样。
public class TableColumnListComparator extends ComparatorChain {
public TableColumnListComparator(ObservableList<? extends TableColumn> columns) {
// Get list of comparators from column list.
for (TableColumn column : columns) {
addComparator(new ColumnComparator(column));
}
}
/**
* Compares two items in a table column as if they were being sorted in the TableView.
*/
private static class ColumnComparator implements Comparator {
private final TableColumn column;
/**
* Default Constructor. Creates comparator based off given table column sort order.
*
* @param column
*/
public ColumnComparator(TableColumn column) {
this.column = column;
}
@Override
public int compare(Object o1, Object o2) {
// Could not find a way to do this without casts unfortunately
// Get the value of the column using the column's cell value factory.
final ObservableValue<?> obj1 = (ObservableValue) column.getCellValueFactory().call(
new TableColumn.CellDataFeatures(column.getTableView(), column, o1));
final ObservableValue<?> obj2 = (ObservableValue) column.getCellValueFactory().call(
new TableColumn.CellDataFeatures(column.getTableView(), column, o2));
// Compare the column values using the column's given comparator.
final int compare = column.getComparator().compare(obj1.getValue(), obj2.getValue());
// Sort by proper ascending or descending.
return column.getSortType() == TableColumn.SortType.ASCENDING ? compare : -compare;
}
}
}
然后,您可以随时使用
Collections.sort(backingList, new TalbeColumnListComparator(table.getSortOrder());
我用它来对多个列表进行相同的排序,在后台线程上排序,在不使用整个列表的情况下进行有效更新等。我认为 Javafx 8 中的表排序会有一些改进,所以这不是必需的在将来。
您也可以使用SortedList
.
SortedList<MatchTableBean> tableItems = new SortedList<>(
observableList, Comparator.comparing(MatchTableBean::isMarker).reversed().thenComparing(MatchTableBean::getQueryRT));
tableItems.comparatorProperty().bind(table.comparatorProperty());
table.setItems(tableItems);
这样,即使内容发生变化或被完全替换,表格也会被排序。
您也可以对 0 个或多个排序列执行此操作:
List<TableColumn<Room, ?>> sortColumns = new LinkedList<>(rooms.getSortOrder());
// rooms.setItems(...)
rooms.getSortOrder().addAll(sortColumns);
你创建一个新的 LinkedList 的原因是你不想像这样指向rooms.getSortOrder()
:
List<TableColumn<Room, ?>> sortColumns = rooms.getSortOrder();
因为这种方式在你调用rooms.getSortOrder()
后sortColumns
都会变成空的,rooms.setItems(...)
这似乎是清除了rooms.getSortOrder()
。