• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:TableRowSorterでJTableのソート
#navi(../)
#tags(JTable, TableRowSorter, JTableHeader)
RIGHT:Posted by &author(aterai); at 2007-02-12
* TableRowSorterでJTableのソート [#m6d46918]
``JDK 6``で導入された、``TableRowSorter``を利用して、``JTable``の行を降順、昇順にソートします。
---
category: swing
folder: TableRowSorter
title: TableRowSorterでJTableのソート
tags: [JTable, TableRowSorter, JTableHeader]
author: aterai
pubdate: 2007-02-12T18:36:03+09:00
description: JDK 6で導入されたTableRowSorterを利用してJTableの行を降順、昇順にソートします。
image: https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTUnbg2jyI/AAAAAAAAAmU/-7yjlGSjBmo/s800/TableRowSorter.png
---
* 概要 [#summary]
`JDK 6`で導入された`TableRowSorter`を利用して`JTable`の行を降順、昇順にソートします。

- &jnlp;
- &jar;
- &zip;
#download(https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTUnbg2jyI/AAAAAAAAAmU/-7yjlGSjBmo/s800/TableRowSorter.png)

#ref(https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTUnbg2jyI/AAAAAAAAAmU/-7yjlGSjBmo/s800/TableRowSorter.png)

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

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

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

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

----
``TableRowSorter``のデフォルトでは、ヘッダクリックで(降順、昇順)とソートが切り替わり、``TableSorter.java``のように(降順、昇順、初期状態)ではなくなっています。上記のサンプルでは、下のボタンをクリックすると、``DefaultRowSorter#setSortKeys(List)``に``null``を代入することで初期状態に戻るようにしています。

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

----
%%第二キーを使ったソートは``TableRowSorter``版では出来ない?ようなので、``TableSorter.java``を使う場合もまだあるかもしれません。%% 複数キーを使ったソートも可能です(ページ下部にあるsyoさんのコメントを参照)。デフォルトではソートキーは``3``つで、ヘッダにマークが表示されるのは最新のソートキーのみですが、クリックした順に保持されるようです。詳しくはドキュメントや[http://syo.cocolog-nifty.com/freely/2006/08/table_616d.html Tableの内容をソート]などを参照してください。
- %%第二キーを使ったソートは`TableRowSorter`版では存在しない?ため`TableSorter.java`を使う場合もまだあるかもしれない。%%
- `TableRowSorter`でも`TableSorter.java`と同様に複数キーを使ったソートが可能
-- ページ下部にあるsyoさんのコメントを参照
- デフォルトではソートキーは`3`つまでクリックした順に保持されるが、ヘッダにマークが表示されるのは最新のソートキーのみ
-- 参考: [http://syo.cocolog-nifty.com/freely/2006/08/table_616d.html Tableの内容をソート]
- [https://tips4java.wordpress.com/2010/08/29/multisort-table-header-cell-renderer/ Multisort Table Header Cell Renderer « Java Tips Weblog]
-- 第二キー以下を薄く表示するサンプルがある
- [[JTableの複数キーを使ったソートをヘッダに表示する>Swing/MultisortHeaderRenderer]]
-- ソートキーの状態を文字列にして追加

- [http://tips4java.wordpress.com/2010/08/29/multisort-table-header-cell-renderer/ Multisort Table Header Cell Renderer « Java Tips Weblog]
-- 第二キー以下を薄く表示するサンプルがあります。

----
- ``TableModel``に要素を追加した後で、``table.setRowSorter(sorter);``とすると、``IndexOutOfBoundsException``: ``Invalid range``が、モデルへの追加、削除、編集中に別の行クリックなどで発生する。
-- 以下のサンプルの場合、``model.fireTableDataChanged()``メソッドを``table.setRowSorter(sorter)``の後で呼び出すと回避できる。
- `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 class RowSorterTest extends JPanel {
  public RowSorterTest() {
    super(new BorderLayout());
    final DefaultTableModel model = new DefaultTableModel(null, new String[] {"A","B","C"});
    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
    // 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(); // <----
    // 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.setSize(320, 240);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}
}}

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

** 参考リンク [#i6859196]
- [http://docs.oracle.com/javase/tutorial/uiswing/components/table.html How to Use Tables]
* 参考リンク [#reference]
- [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/table/TableRowSorter.html TableRowSorter (Java Platform SE 8)]
- [https://docs.oracle.com/javase/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]
#comment
- `DefaultRowSorter#setMaxSortKeys(int)`で複数のキーを用いたソートも出来ているように思います(`b86`)。ただ、ヘッダー部分がわかりにくいですが。 -- &user(syo); &new{2006-08-03 (木) 11:12:55};
-- ご指摘ありがとうございます。なるほど、こちら([http://syo.cocolog-nifty.com/freely/2006/08/table_616d.html Tableの内容をソート])を使えばうまくいきそうですね。解説を修正しました。 -- &user(aterai); &new{2006-08-03 (木) 12:34:53};
- `renderer`がないので、基本的に数字は左揃え、文字列は右揃えで、中央揃えするにはどうすれば宜しいでしょうか? -- &user(パンダ); &new{2007-06-14 (木) 09:40:20};
--長いので[[JTableのセル文字揃え>Swing/CellTextAlignment]]に移動しました。 -- &user(aterai); &new{2007-06-14 (木) 13:19:36};

#comment