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 Comparator
s
Here's another option for implementing a custom sort.
The advantage of this technique is that it's controlled by the arbitrary Comparator
s that you define.
A disadvantage is that there's no visual indicator for the selected sort on the column header.
First, define the different
Comparator
s
you need, perhaps directly in your Model Object. (These Comparator
s 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 Comparator
s
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 Comparator
s
MainWindow
- wires the clicks on the table header to a method call on the table model (here called sortByColumn
)
MovieTableModel
- uses the Comparator
s to sort its list of Model Objects