Ordering via SortedList (and Properties Extractor)

Quite a while ago (almost 1,5 years 😱) I wrote a post about the JavaFX way to get ListViews and TableViews instantly updated on model data change: using Properties Extractor pattern.

TableColumns have a build-in support for sorting the data per column: just double-click the column header (. But how to order ListViews or get the table content get ordered by certain predicate instantly on data changes?

To sort elements the ObervableList has a sort(Comparator<? super E> c) method to sort the list according to the order induced by the specified Comparator (each time it is called).
Note: If the specified comparator is null then all elements in this list must implement the Comparable interface and the elements’ natural ordering should be used.

I have extended the demo app in terms of sorting:
GET THE APP HERE.
GET THE CODE HERE.
extractor_demo_main

SortedList and FilteredList

SortedList and FilteredList are very interesting and useful wrapper for OberservableLists to keep the content sorted and/or filtered (will add filtering soon).

SortedList: Wraps an ObservableList and sorts it’s content. All changes in the ObservableList are propagated immediately to the SortedList.

FilteredList: Wraps an ObservableList and filters it’s content using the provided Predicate. All changes in the ObservableList are propagated immediately to the FilteredList.

You can create a SortedList by creating it “manually”:

personSortedList = new SortedList(model.getPersonFXBeans());

or let the ObservableList do it for you:

personSortedList = model.getPersonFXBeans().sorted();

“Readonly TableView” and “ListView” are sharing the same SortedList wrapper:

readOnlyListView.setItems(personSortedList);
readOnlyTableView.setItems(personSortedList);

Sorting

extractor_demo_comparators

The “Sorting” ComboBox contains the available comparators for the SortedList:

personComparators = FXCollections.observableArrayList(new FirstNameComparator(),
                new LastNameComparator(),
                new DateOfBirthComparator(),
                new AgeComparator(),
                new DaysToNextBirthdayComparator(),
                new NextBirthdayComparator()
);
personOrderByComboBox.setItems(personComparators);
@FXML
public void onSortByComparator() {
  personSortedList.setComparator(personOrderByComboBox.getSelectionModel().getSelectedItem());
}

Also there is a toggle for the sort direction:

@FXML
public void onChangeSortDirection() {
  personSortedList.setComparator(personSortedList.getComparator().reversed());
}

The “Editable TableView” is still “self-sufficient” in terms of sorting.

All three views are sharing the same data model (model.getPersonFXBeans()) and editing the content is instantly notified by them (via property extractor).

If you play with the app by changing the data: note also the sorting take effect. 

One more thing

If you bind the comparatorProperty() of SortedList to the TableView, the sorting the content is triggered by the build-in ordering options ig TableView (via column header):

personSortedList.comparatorProperty().bind(editableTableView.comparatorProperty());

Note that other ways to trigger the SortedList e.g. by setCompartor() will fail then with exception as comparatorProperty is already bound.

3 thoughts on “Ordering via SortedList (and Properties Extractor)”

Leave a Reply

Your email address will not be published. Required fields are marked *