JTable.setAutoCreateRowSorter(true).
This will attach a generic sorter to your table.
The sorting is controlled by clicking on the column headers.
Example
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Collections; import java.util.List; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.RowSorter; public class GenericTableSort { /** Simplest way to add sorting to a table. */ public static void main(String... aArgs){ GenericTableSort app = new GenericTableSort(); app.buildAndDisplayGui(); } // PRIVATE private void buildAndDisplayGui(){ JFrame frame = new JFrame("Test Generic Table Sort"); addSortableTableTo(frame); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } private void addSortableTableTo(JFrame aFrame){ JPanel panel = new JPanel(); Object[][] data = { {1,"T"}, {2,"B"}, {3,"A"}, {4, "F"}}; String[] cols = {"One", "Two"}; final JTable table = new JTable(data, cols); table.setAutoCreateRowSorter(true); //a generic sorter //without the scroll pane, you won't see the headers panel.add(new JScrollPane(table)); JButton revert = new JButton("Revert Sort"); revert.addActionListener( new ActionListener(){ @Override public void actionPerformed(ActionEvent aEvent) { List<RowSorter.SortKey> NO_SORT = Collections.emptyList(); table.getRowSorter().setSortKeys(NO_SORT); } }); panel.add(revert); aFrame.getContentPane().add(panel); } }
The above example unsorts the table when a button is clicked.
To unsort a table, and revert it back to its original state, you simply pass a null or empty List
to this method:
table.getRowSorter().setSortKeys(List)
Custom sorting with SortKeys
In some cases, you may want more control over sorting.
For example, you may need to implement a sort that depends on more than one column (a common requirement).
One option is to use a list of
SortKey
objects to control the sorting.
Example:
import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.RowSorter; import javax.swing.SortOrder; import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; public class TableSortWithSortKey { /** Custom table sorting, using SortKey. */ public static void main(String... aArgs){ TableSortWithSortKey app = new TableSortWithSortKey(); app.buildAndDisplayGui(); } // PRIVATE private JTable fTable; private RowSorter<TableModel> fSorter; private void buildAndDisplayGui(){ JFrame frame = new JFrame("Test Table Sort With Sort Key"); addSortableTableTo(frame); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } private void addSortableTableTo(JFrame aFrame){ JPanel panel = new JPanel(); Object[][] data = { {1,"T"}, {2,"B"}, {3,"A"}, {4, "F"}}; String[] cols = {"One", "Two"}; fTable = new JTable(data, cols); fSorter = new TableRowSorter<>(fTable.getModel()); fTable.setRowSorter(fSorter); fTable.getTableHeader().addMouseListener(new CustomSorter()); panel.add(new JScrollPane(fTable)); aFrame.getContentPane().add(panel); } /** Default sort behaviour, plus every third click removes the sort. */ private final class CustomSorter extends MouseAdapter { @Override public void mouseClicked(MouseEvent aEvent) { int columnIdx = fTable.getColumnModel().getColumnIndexAtX(aEvent.getX()); //build a list of sort keys for this column, and pass it to the sorter //you can build the list to fit your needs here //for example, you can sort on multiple columns, not just one List<RowSorter.SortKey> sortKeys = new ArrayList<>(); //cycle through all orders; sort is removed every 3rd click SortOrder order = SortOrder.values()[fCountClicks % 3]; sortKeys.add(new RowSorter.SortKey(columnIdx, order)); fSorter.setSortKeys(sortKeys); ++fCountClicks; } private int fCountClicks; } }
Custom sorting with Comparators
Here's another option for implementing a custom sort.
The advantage of this technique is that it's controlled by the arbitrary Comparators that you define.
A disadvantage is that there's no visual indicator for the selected sort on the column header.
First, define the different
Comparators
you need, perhaps directly in your Model Object. (These Comparators know nothing about the user interface,
but they are ultimately responsible for the actual sorting.)
Then it becomes a case of wiring together clicks on the column header to the proper Comparator,
sorting the data underlying your TableModel, and then refreshing the screen.
More precisely:
MouseAdapter to the JTableHeader, to listen for clicks on the table's header.
TableModel to sort itself on the given column index; these sorts are implemented by
the N different Comparators
that you've defined for this purpose.
fireTableDateChanged() in the TableModel.
myTable.getTableHeader().addMouseListener(new MySorter());
private final class MySorter extends MouseAdapter {
@Override public void mouseClicked(MouseEvent aEvent) {
int colIdx = myTable.getColumnModel().getColumnIndexAtX(aEvent.getX());
myTableModel.sortByColumn(colIdx);
}
}
The above technique is implemented by the Movies app,
using the following classes:
Movie - the Model Object, that defines the needed Comparators
MainWindow - wires the clicks on the table header to a method call on the table model (here called sortByColumn)
MovieTableModel - uses the Comparators to sort its list of Model Objects