我有一个与TreeView关联的TableView。每次选择TreeView中的节点时,TableView都会刷新不同的数据。
我能够对TableView中的任何列进行排序,只需按下相应的列标题即可。这很好。
但是:当我在树视图中选择一个不同的节点时,尽管列标题仍然显示为已排序。数据不是。
有没有办法以编程方式强制执行每次数据更改时用户所做的排序顺序?
答案 0 :(得分:16)
好的,我发现了怎么做。我会在这里总结一下,以防它对其他人有用:
在之前更新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
}
我没有考虑在排序中有多列的可能性,但这对于这些信息来说非常简单。
答案 1 :(得分:11)
我遇到了同样的问题,发现在更新数据后你只需要在表视图上调用函数sort():
TableView rooms;
...
// Update data of rooms
...
rooms.sort()
表视图知道用于排序的列,因此sort函数将按所需顺序对新数据进行排序。 此功能仅在Java 8中可用。
答案 2 :(得分:6)
如果您的TableView未重新初始化,您还可以执行以下操作:
TableColumn<BundleRow, ?> sortOrder = rooms.getSortOrder().get(0);
rooms.getSortOrder().clear();
rooms.getSortOrder().add(sortOrder);
答案 3 :(得分:6)
fornacif的示例有效,但如果有多个排序顺序则不行(尝试按住Shift键单击第二列以创建二级排序顺序)。
要对所有列进行重新排序,您需要执行以下操作:
List<TableColumn<Room, ?>> sortOrder = new ArrayList<>(roomTable.getSortOrder());
roomTable.getSortOrder().clear();
roomTable.getSortOrder().addAll(sortOrder);
答案 4 :(得分:3)
如果使用TableView.setItems()方法,它似乎会重置TableView的几个方面。将ObservableList保留在TableView中,清除其内容,然后添加新项。然后,TableView.sort()仍然知道哪些列先前已经排序,它将工作。像这样:
tableView.getItems().clear();
tableView.getItems().addAll(newTableData);
tableView.sort();
答案 5 :(得分:2)
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中的表排序会有一些改进,所以这会赢得'将来有必要。
答案 6 :(得分:0)
您也可以使用SortedList
。
SortedList<MatchTableBean> tableItems = new SortedList<>(
observableList, Comparator.comparing(MatchTableBean::isMarker).reversed().thenComparing(MatchTableBean::getQueryRT));
tableItems.comparatorProperty().bind(table.comparatorProperty());
table.setItems(tableItems);
通过这种方式可以对表格进行排序,即使内容发生更改或完全替换也是如此。
答案 7 :(得分:0)
您还可以对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()
。