I'm having troubles sorting my JFXTreeTableView
(from Jfoenix).
I have created an object named ScanModel which extends Jfoenix's RecursiveTreeObject<ScanModel>
.
One of the many properties I'm having there is:
private IntegerProperty id;
Here are its getters and setters
public final IntegerProperty idProperty() {
if (id == null) {
id = new SimpleIntegerProperty();
}
return id;
}
public final int getId() {
return idProperty().get();
}
public void setId(int value) {
idProperty().set(value);
}
Two classes extend the abstract ScanModel class: StudyModel and SeriesModel.
StudyModel (which contains multiple SeriesModels) overrides getChildren()
method of Jfoenix RecursiveTreeObject, and returns its series observable list.
Here is how I bind the observable list which contain the items to the table itself:
protected void createTree(JFXTreeTableView<ScanModel> tree, ObservableList<ScanModel> elements) {
tree.setRoot(new RecursiveTreeItem<ScanModel>(elements, RecursiveTreeObject::getChildren));
tree.setShowRoot(false);
tree.getSelectionModel().clearSelection();
}
Until now everything worked great, I've added new ScanModel items to the observable list, and it was automatically displyed in the UI.
Now for my issue:
The client requests sorted table: Descending StudyModels, and Ascending SeriesModels.
For first try I only tried to sort the StudyModels.
I've changed the createTree method to this implementation:
protected void createTree(JFXTreeTableView<ScanModel> tree, ObservableList<ScanModel> elements) {
SortedList<ScanModel> sortedElements = elements.sorted((l, r) -> Integer.compare(l.getId(), r.getId()));
tree.setRoot(new RecursiveTreeItem<ScanModel>(sortedElements, RecursiveTreeObject::getChildren));
tree.setShowRoot(false);
tree.getSelectionModel().clearSelection();
}
The sorted observable list is indeed sorted, but it does not reflect in the UI
What am I missing here?
Thanks.
Update
Just in case, here is the fxml of the table
<JFXTreeTableView fx:id="_treeTableView">
<placeholder>
<Label text="No Normal Studies to display" />
</placeholder>
<columnResizePolicy>
<JFXTreeTableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
<columns>
<JFXTreeTableColumn text="ID" sortable="false"
minWidth="150" maxWidth="150">
<cellValueFactory>
<TreeTableErrorIndicationCellFactory value="id" />
</cellValueFactory>
</JFXTreeTableColumn>
<JFXTreeTableColumn text="Scan Time" sortable="false"
minWidth="140" maxWidth="140">
<cellValueFactory>
<TreeTableErrorIndicationCellFactory value="formattedScanTime" />
</cellValueFactory>
</JFXTreeTableColumn>
<JFXTreeTableColumn text="Selected" sortable="false"
minWidth="60" maxWidth="60">
<cellValueFactory>
<ScanSelectedValueFactory />
</cellValueFactory>
</JFXTreeTableColumn>
<JFXTreeTableColumn sortable="false">
</JFXTreeTableColumn>
<JFXTreeTableColumn text="Archived" sortable="false"
style="-fx-alignment: CENTER-RIGHT;" minWidth="60" maxWidth="60">
<cellValueFactory>
<IsArchivedCellFactory />
</cellValueFactory>
</JFXTreeTableColumn>
</columns>
</JFXTreeTableView>
It's been a while since the question was asked, and I see that some people viewed the topic.
Here is an answer. Surely not the best one - but it works.
First of all, while creating the tree - need to setSortPolicy
of the tree.
Here is how it looks like in my project:
protected void createTree(JFXTreeTableView<ScanModel> tree, ObservableList<ScanModel> elements) {
tree.setRoot(new RecursiveTreeItem<ScanModel>(elements, RecursiveTreeObject::getChildren));
tree.setShowRoot(false);
tree.getSelectionModel().clearSelection();
// set sort policy for the table in two levels
tree.setSortPolicy(t -> {
Comparator<TreeItem<ScanModel>> studiesComparator = (r1, r2) -> {
try {
int r1Value = Integer.parseInt(r1.getValue().getDisplayName());
int r2Value = Integer.parseInt(r2.getValue().getDisplayName());
return Integer.compare(r2Value, r1Value);
} catch (NumberFormatException e) {
return r2.getValue().getDisplayName().compareToIgnoreCase(r1.getValue().getDisplayName());
}
};
FXCollections.sort(tree.getRoot().getChildren(), studiesComparator);
for (TreeItem<ScanModel> series : tree.getRoot().getChildren()) {
Comparator<TreeItem<ScanModel>> seriesComparator = (r1, r2) -> {
try {
int r1Value = Integer.parseInt(r1.getValue().getDisplayName());
int r2Value = Integer.parseInt(r2.getValue().getDisplayName());
return Integer.compare(r1Value, r2Value);
} catch (NumberFormatException e) {
return r1.getValue().getDisplayName().compareToIgnoreCase(r2.getValue().getDisplayName());
}
};
series.getChildren().sort(seriesComparator);
}
return true;
});
}
Second, For each new item added to the tree - I call the sort
method.
/**
* Sort the table according to the configured sort policy
*
* @param tree
*/
protected void sortTree(JFXTreeTableView<ScanModel> tree) {
// Keep selected row and set it again after sort
TreeItem<ScanModel> selectedRow = tree.getSelectionModel().getSelectedItem();
tree.sort();
tree.getSelectionModel().select(selectedRow);
}
Hope it will help some future viewers.
Naor