I extended the TableRowSorter class to get the desired effect. In my case I wanted to sort all columns descending first, except for the first column. The following code allows to specify which columns should be sorted ascending first.
/** Class sorting table descending on first click unless column is specified
* in constructor to follow standard behaviour (ascending on first click).
* @author Adam Jagosz */
class NormallyDescendingSorter extends TableRowSorter {
/** columns to be sorted in a standard way, ascending on first click */
ArrayList<Integer> ascendingColumns;
/** Constructor
* @param model table model to be sorted
* @param ascendingColumns columns to follow ascending sort on first click */
public NormallyDescendingSorter(TableModel model, int... ascendingColumns) {
super(model);
this.ascendingColumns = new ArrayList<>();
for (int index = 0; index < ascendingColumns.length; index++)
{
this.ascendingColumns.add(ascendingColumns[index]);
}
}
/**
* Method sorting table rows upon clicking on column header
* @param column column to sort by */
@Override
public void toggleSortOrder(int column) {
if(ascendingColumns.contains(column)) {
super.toggleSortOrder(column);
return;
}
ArrayList<SortKey> sortKeys = new ArrayList<>(getSortKeys());
if(sortKeys.isEmpty() || sortKeys.get(0).getColumn() != column) {
sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING));
}
else if (sortKeys.get(0).getSortOrder() == SortOrder.ASCENDING) {
sortKeys.removeIf(key -> key.getColumn() == column);
sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING));
}
else {
sortKeys.removeIf(key -> key.getColumn() == column);
sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.ASCENDING));
}
setSortKeys(sortKeys);
}
}
You can use this like that:
DocumentTableModel model = new DocumentTableModel(document);
JTable table = new JTable(model);
NormallyDescendingSorter sorter = new NormallyDescendingSorter(model, 0);
table.setRowSorter(sorter);
(I specified 0 as column index to be sorted ascending).