我有一个与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的几个方面。将ObservableList保留在TableView中,清除其内容,然后添加新项。然后,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);
这样就可以对表进行排序,即使内容发生变化或被完全替换。