TITLE:TableRowSorterでJTableのソート

TableRowSorterでJTableのソート

Posted by terai at 2007-02-12

概要

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

  • &jnlp;
  • &jar;
  • &zip;

#screenshot

サンプルコード

TestModel model = new TestModel();
JTable table = new JTable(model);
RowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);

解説

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

TableRowSorterのデフォルトでは、ヘッダクリックで(降順、昇順)とソートが切り替わり、TableSorterのように(降順、昇順、初期状態)ではなくなっています。上記のサンプルでは、下のボタンをクリックすると、DefaultRowSorter#setSortKeys(List)にnullを代入することで初期状態に戻るようにしていますが、SwingLabsのJXTableみたいにShift+ヘッダクリックで初期状態に戻るようにしてもいいかもしれません(参考:TableRowSorterのSortKeysをクリアする)。

また、DefaultRowSorter#setSortable(int, boolean)でソートしたくないカラムを以前より簡単に指定できます(参考:JTableHeaderのカラムを選択不可にする)。

第二キーを使ったソートはTableRowSorter版では出来ない?ようなので、TableSorter.javaを使う場合もまだあるかもしれません。 複数キーを使ったソートも可能です。デフォルトではソートキーは3つで、ヘッダにマークが表示されるのは最新のソートキーのみですが、クリックした順に保持されるようです。詳しくはドキュメントやTableの内容をソートなどを参照してください。


RowSorter を直接指定しなくても、autoCreateRowSorter(true) とすると、JTable が自動的に RowSorter を作成して、ソートが出来るようになります。

JTable table = new JTable(model);
table.setAutoCreateRowSorter(true);

参考リンク

コメント

  • DefaultRowSorter#setMaxSortKeys(int)で複数のキーを用いたソートも出来ているように思います(b86)。ただ、ヘッダー部分がわかりにくいですが。 -- syo
    • ご指摘ありがとうございます。なるほど、こちら(Tableの内容をソート)を使えばうまくいきそうですね。 -- terai
  • rendererがないので、基本的に数字は左揃え、文字列は右揃えで、中央揃えするにはどうすれば宜しいでしょうか? -- パンダ
    • JTableは、Object、Number、Booleanクラスのデフォルトセルレンダラーを持っているため、モデル*1が各列のクラスを正しく返すように、TableModel#getColumnClass(int)をオーバーライドしてやると、そのクラスのデフォルトセルレンダラーが使用され*2、表示は数字右揃え、文字列左揃え*3になります。
      //ちょっとしたサンプルの場合は、以下のようにオーバーライドすると便利かも?
      String[] columnNames = {"String", "Integer", "Boolean"};
      Object[][] data = {
        {"AAA", 1, true},
        {"BBB", 2, false},
      };
      DefaultTableModel model = new DefaultTableModel(data, columnNames) {
        @Override
        public Class<?> getColumnClass(int column) {
          return getValueAt(0, column).getClass();
        }
      };
      JTable table = new JTable(model);
      
      クラスのデフォルトセルレンダラーではなく、任意の列にセルレンダラーを割り当てて、例えば中揃えにしたい場合は、以下のように設定します。 -- terai
      DefaultTableCellRenderer r = new DefaultTableCellRenderer();
      r.setHorizontalAlignment(JLabel.CENTER);
      table.getColumnModel().getColumn(2).setCellRenderer(r);