• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:TableRowSorterでJTableのソート
#navi(../)
RIGHT:Posted by [[aterai]] at 2007-02-12
*TableRowSorterでJTableのソート [#m6d46918]
JDK 6 で導入された、TableRowSorterを利用して、JTableの行を降順、昇順にソートします。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(http://lh4.ggpht.com/_9Z4BYR88imo/TQTUnbg2jyI/AAAAAAAAAmU/-7yjlGSjBmo/s800/TableRowSorter.png)

**サンプルコード [#ibb86eb9]
#code{{
TableModel model = makeTestTableModel();
JTable table = new JTable(model);
RowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
}}

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

以下のように、JTable#autoCreateRowSorter(true); メソッドを使用した場合も、JTable が自動的に RowSorter を作成して、ソートが出来るようになります。
#code{{
JTable table = new JTable(model);
table.setAutoCreateRowSorter(true);
}}

----
TableRowSorterのデフォルトでは、ヘッダクリックで(降順、昇順)とソートが切り替わり、TableSorterのように(降順、昇順、初期状態)ではなくなっています。上記のサンプルでは、下のボタンをクリックすると、DefaultRowSorter#setSortKeys(List)にnullを代入することで初期状態に戻るようにしています。
-SwingLabsのJXTableのように「Shift+ヘッダクリック」で初期状態
--[[TableRowSorterのSortKeysをクリアする>Swing/ClearSortingState]]
-TableSorter.javaのようにヘッダクリックで降順、昇順、初期状態とループ
--[[TableRowSorterのソートをヘッダクリックで昇順、降順、初期状態に変更>Swing/TriStateSorting]]

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

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

#code{{
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);
  }
}
}}
- [http://java.sun.com/javase/ja/6/docs/ja/api/javax/swing/RowSorter.html RowSorter (Java Platform SE 6)]
-- RowSorter の具象実装は、TableModel、ListModel などのモデルを参照する必要があります。JTable や JList などのビュークラスも、モデルを参照します。順序の依存性を回避するため、RowSorter 実装がモデル上にリスナーをインストールしないようにしてください。モデルが変更されると、ビュークラスが RowSorter を呼び出します。たとえば、TableModel JTable で行が更新された場合、 rowsUpdated が呼び出されます。モデルが変更されると、ビューは、 modelStructureChanged、allRowsChanged、rowsInserted、rowsDeleted、rowsUpdated のいずれかのメソッドを呼び出します。

**参考リンク [#i6859196]
-[http://java.sun.com/docs/books/tutorial/uiswing/components/table.html How to Use Tables]
-[[TableSorterでJTableをソート>Swing/TableSorter]]
-[[TableRowSorterのSortKeysをクリアする>Swing/ClearSortingState]]
-[[TableRowSorterのソートをヘッダクリックで昇順、降順、初期状態に変更>Swing/TriStateSorting]]
-[http://syo.cocolog-nifty.com/freely/2006/08/table_616d.html Tableの内容をソート]

**コメント [#dee0fa5e]
- DefaultRowSorter#setMaxSortKeys(int)で複数のキーを用いたソートも出来ているように思います(b86)。ただ、ヘッダー部分がわかりにくいですが。 -- [[syo]] &new{2006-08-03 (木) 11:12:55};
-- ご指摘ありがとうございます。なるほど、こちら([http://syo.cocolog-nifty.com/freely/2006/08/table_616d.html Tableの内容をソート])を使えばうまくいきそうですね。 -- [[aterai]] &new{2006-08-03 (木) 12:34:53};
- rendererがないので、基本的に数字は左揃え、文字列は右揃えで、中央揃えするにはどうすれば宜しいでしょうか? -- [[パンダ]] &new{2007-06-14 (木) 09:40:20};
--長いので[[JTableのセル文字揃え>Swing/CellTextAlignment]]に移動しました。 -- [[aterai]] &new{2007-06-14 (木) 13:19:36};

#comment