可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a TableView associated to a TreeView. Each time a node in the TreeView is selected, the TableView is refreshed with different data.
I am able to sort any column in the TableView, just pressing the corresponding column header. That works fine.
But: when I select a different node in the tree-view, eventhough the column headers keep showing as sorted. The data is not.
Is there a way to programmatically enforce the sort order made by the user each time the data changes?
回答1:
Ok, I found how to do it. I will summarize it here in case it is useful to others:
Before you update the contents of the TableView, you must save the sortcolum (if any) and the sortType:
TableView rooms;
...
TableColumn sortcolumn = null;
SortType st = null;
if (rooms.getSortOrder().size()>0) {
sortcolumn = (TableColumn) rooms.getSortOrder().get(0);
st = sortcolumn.getSortType();
}
Then, after you are done updating the data in the TableView, you must restore the lost sort-column state and perform a sort.
if (sortcolumn!=null) {
rooms.getSortOrder().add(sortcolumn);
sortcolumn.setSortType(st);
sortcolumn.setSortable(true); // This performs a sort
}
I do not take into account the possibility of having multiple columns in the sort, but this would be very simple to do with this information.
回答2:
I had the same problem and found out that after an update of the data you only have to call the function sort() on the table view:
TableView rooms;
...
// Update data of rooms
...
rooms.sort()
The table view knows the columns for sorting thus the sort function will sort the new data in the wanted order.
This function is only available in Java 8.
回答3:
If your TableView is not reinitialized, you can also do the following:
TableColumn<BundleRow, ?> sortOrder = rooms.getSortOrder().get(0);
rooms.getSortOrder().clear();
rooms.getSortOrder().add(sortOrder);
回答4:
The example of fornacif works, but not if there is more than one sort order (try shift-click on a second column to create secondary sort order).
To do a re-sort on all columns you would need to do something like this:
List<TableColumn<Room, ?>> sortOrder = new ArrayList<>(roomTable.getSortOrder());
roomTable.getSortOrder().clear();
roomTable.getSortOrder().addAll(sortOrder);
回答5:
If you use the TableView.setItems() method, it appears to reset several aspects of the TableView. Leave the ObservableList in the TableView in place, clear its contents, and then add your new items. Then, TableView.sort() will still know which columns were previously sorted and it will work. Like this:
tableView.getItems().clear();
tableView.getItems().addAll(newTableData);
tableView.sort();
回答6:
Marco Jakob's answer is good for most cases, but I found that I needed to create a comparator that matches the table sort order for more flexibility. You can then use any method that takes a comparator to do sorting, searching, etc. To create the comparator, I extended that ComparatorChain class from apache's Common-Collections to easily do multiple column sorting. It looks like this.
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;
}
}
}
You can then sort at anytime with
Collections.sort(backingList, new TalbeColumnListComparator(table.getSortOrder());
I use this to sort multiple lists with the same sort, sort on background threads, do efficient updates without resorting the whole list, etc. I think there are going to be some improvements to table sorting in Javafx 8 so this won't be necessary in the future.
回答7:
You can also use a SortedList
.
SortedList<MatchTableBean> tableItems = new SortedList<>(
observableList, Comparator.comparing(MatchTableBean::isMarker).reversed().thenComparing(MatchTableBean::getQueryRT));
tableItems.comparatorProperty().bind(table.comparatorProperty());
table.setItems(tableItems);
This way the table is sorted, even when the content changes or is completely replaced.