0

Javafx TableView sorting uses ascending order first when clicking on a column header, then descending order on second click. I have a table with sports team data with columns for wins, losses etc. Wins should be sorted by default in descending order and losses in ascending order so the best team in each category is always on top when clicking once on a header.

I have tried sortType="DESCENDING" in the fxml file and setSortType(TableColumn.SortType.DESCENDING) in code with no effect.

ank
  • 11
  • 2
  • astonishingly, the cycling in sortOrders is hard-coded (in TableColumnHeader, private method sortColumn) to unsorted -> ascending -> descending -> unsorted - so nothing we can do. At least not without going dirty: a) fake ascending/descending to the respective other by setting a inverted comparator (drawback: wrong icon) or b) implement a custom TableColumnHeader with a replaced onMouseReleasedHandler that calls a custom method to cycle sort order (drawback: reflective fiddling in internals necessary - or custom jfx image) – kleopatra Dec 03 '20 at 13:14
  • Thank you, all valuable info. I found a solution that works great for my use case, will post it as an answer. – ank Dec 03 '20 at 14:45

1 Answers1

1

In my use case the secondary sorting option is more of a hinderance. The solution I came up with only allows sorting a column in one way, clicking the header toggles between sorted and not used for sorting.

Only allowing descending sorting is simpler and only requires a listener to the table sortOrder. Only allowing ascending sorting however requires adding a listener to the column sortTypeProperty and for multisorting using the shift-key to work correctly the correct sorting must also be forced in the table sortOrder listener.

columnLosses.sortTypeProperty().addListener(o -> {
    if (columnLosses.getSortType().equals(TableColumn.SortType.DESCENDING)) {
        table.getSortOrder().remove(columnLosses);
    }
});
table.getSortOrder().addListener((Observable o) -> {
    if (table.getSortOrder().contains(columnWins)) {
        columnWins.setSortType(TableColumn.SortType.DESCENDING);
    }
    if (columnLosses.getSortType().equals(TableColumn.SortType.DESCENDING)) {
        columnLosses.setSortType(TableColumn.SortType.ASCENDING); // needed for correct multicolumn sorting
    }
});
ank
  • 11
  • 2