概要

JDK 6で導入されたTableRowSorterを利用してJTableの行を降順、昇順にソートします。

サンプルコード

TableModel model = makeTestTableModel();
JTable table = new JTable(model);
RowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
View in GitHub: Java, Kotlin

解説

JDK 6ではJTableTableRowSorterを設定することでカラムヘッダのクリックによる行ソートが行えます。

  • 以下のようにJTable#autoCreateRowSorter(true)メソッドを使用した場合も、JTableが自動的にRowSorterを作成してソートが可能になる
    JTable table = new JTable(model);
    table.setAutoCreateRowSorter(true);
    

  • TableRowSorterのデフォルトではヘッダクリックで(降順、昇順)とソートが切り替わり、TableSorter.javaのように(降順、昇順、初期状態)ではなくなっている
    • このページのサンプルではBorderLayout.SOUTHに配置したボタンをクリックするとDefaultRowSorter#setSortKeys(List)nullを代入することで初期状態に戻るよう設定している
  • SwingLabsJXTableのように「Shift+ヘッダクリック」で初期状態に戻す
  • TableSorter.javaのようにヘッダクリックで降順、昇順、初期状態とループ


  • TableModelに要素を追加した後でtable.setRowSorter(sorter);とすると、IndexOutOfBoundsException: Invalid rangeがモデルへの追加、削除、編集中に別の行クリックなどで発生する
    • 以下のサンプルの場合model.fireTableDataChanged()メソッドをtable.setRowSorter(sorter)の後で呼び出すと回避可能
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class RowSorterTest extends JPanel {
  public RowSorterTest() {
    super(new BorderLayout());
    final DefaultTableModel model = new DefaultTableModel(null, new String[] {"A", "B", "C"});
    JTable table = new JTable(model);
    TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
    // table.setRowSorter(sorter); // OK
    model.addRow(new String[] {"aa", "bb", "cc"});
    model.addRow(new String[] {"dd", "ee", "ff"});
    table.setRowSorter(sorter); // IndexOutOfBoundsException: Invalid range
    // model.fireTableDataChanged(); // <----
    add(new JButton(new AbstractAction("model.addRow(...); -> IndexOutOfBoundsException") {
      @Override public void actionPerformed(ActionEvent e) {
        model.addRow(new String[] {"gg", "hh", "ii"});
      }
    }), BorderLayout.SOUTH);
    add(new JScrollPane(table));
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() { createAndShowGUI(); }
    });
  }

  public static void createAndShowGUI() {
    JFrame frame = new JFrame("Test");
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new RowSorterTest());
    frame.setSize(320, 240);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}
  • RowSorter (Java Platform SE 8)

    RowSorterの具象実装は、TableModelListModelなどのモデルを参照する必要があります。JTableJListなどのビュークラスも、モデルを参照します。順序の依存性を回避するため、RowSorter実装がモデル上にリスナーをインストールしないようにしてください。モデルが変更されると、ビュークラスがRowSorterを呼び出します。例えば、TableModel JTable で行が更新された場合、rowsUpdatedが呼び出されます。モデルが変更されると、ビューは、modelStructureChangedallRowsChangedrowsInsertedrowsDeletedrowsUpdatedのいずれかのメソッドを呼び出します。

参考リンク

コメント