Swing/TableSorter の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/TableSorter へ行く。
- Swing/TableSorter の差分を削除
--- category: swing folder: TableSorter title: TableSorterでJTableをソート tags: [JTable, TableSorter] author: aterai pubdate: 2005-02-28T18:44:05+09:00 description: JDK 1.5.0以前に、The Java™ Tutorialに存在したTableSorter.javaを使用して、JTableの行を降順、昇順、初期状態にソートします。 image: https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTUp0MLx6I/AAAAAAAAAmY/omjw4LoJbbc/s800/TableSorter.png --- * 概要 [#summary] `JDK 1.5.0`以前に、`The Java™ Tutorial`に存在した`TableSorter.java`を使用して、`JTable`の行を降順、昇順、初期状態にソートします。 #download(https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTUp0MLx6I/AAAAAAAAAmY/omjw4LoJbbc/s800/TableSorter.png) * サンプルコード [#sourcecode] #code(link){{ // DefaultTableModel model = new DefaultTableModel(); TestModel model = new TestModel(); TableSorter sorter = new TableSorter(model); JTable table = new JTable(sorter); sorter.setTableHeader(table.getTableHeader()); }} * 解説 [#explanation] `The Java™ Tutorial`版の`TableSorter`を使用して、[[JTableのソート>Swing/SortableTable]]で使用しているものと同じ`TableModel`をソートしています。 `TableSorter`には、KBD{Ctrl}キーを押しながらヘッダをクリックすると、そのカラムを第`2`キー、第`3`キーとしてソートする機能もあります。 - `TableSorter`にはKBD{Ctrl}キーを押しながらヘッダをクリックすると、そのカラムを第`2`キー、第`3`キーとしてソートする機能もある - `JDK 1.5.0`で`Generics`の警告を出さないようにするには`TableSorter.java`に以下のような修正が必要 `JDK 1.4.x`と`Windows XP`の環境で、ヘッダにカーソルを置いてもロールオーバーしない場合があるようです。上記のスクリーンショットは`JDK 1.5.0_01`で撮っています。 ---- - `JDK 1.5.0`で`Generics`の警告を出さないようにするには、`TableSorter.java`に以下のような修正が必要 #code{{ private static class ComparableComparator implements Comparator { @SuppressWarnings("unchecked") public int compare(Object o1, Object o2) { return ((Comparable) o1).compareTo(o2); } } public static final ComparableComparator COMPARABLE_COMAPRATOR = new ComparableComparator(); public static final ComparableComparator LEXICAL_COMPARATOR = new ComparableComparator() { @SuppressWarnings("unchecked") public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString()); } }; private TableModelListener tableModelListener; private Map<Class, Comparator> columnComparators = new HashMap<>(); private List<Directive> sortingColumns = new ArrayList<>(); protected ComparableComparator getComparator(int column) { Class columnType = tableModel.getColumnClass(column); ComparableComparator comparator = (ComparableComparator) columnComparators.get(columnType); if (comparator != null) { return comparator; } // ... private class Row implements Comparable<Row> { private int modelIndex; public Row(int index) { this.modelIndex = index; } public int compareTo(Row o) { int row1 = modelIndex; int row2 = o.modelIndex; // ... }} ---- `LookAndFeel`を動作中に切り替える場合は、`sorter.setTableHeader(table.getTableHeader());`で設定した`JTableHeader`を新しい`LookAndFeel`を適用したものに入れ替えておかないと、`NullPointerException`が発生します。 - `LookAndFeel`を動作中に切り替える場合は、`sorter.setTableHeader(table.getTableHeader());`で設定した`JTableHeader`を新しい`LookAndFeel`を適用したものに入れ替えておかないと`NullPointerException`が発生する #code{{ private final TableSorter sorter = new TableSorter(model); private final JTable table = new JTable(sorter) { @Override public void updateUI() { sorter.setTableHeader(null); super.updateUI(); EventQueue.invokeLater(new Runnable() { @Override public void run() { JTableHeader h = table.getTableHeader(); sorter.setTableHeader(h); h.repaint(); } }); } }; }} ---- - `JDK 1.6.0`から`JTable`には標準でソート機能が追加された //-- [http://java.sun.com/developer/JDCTechTips/2005/tt1115.html#2 SORTING AND FILTERING TABLES] -- [http://www.oracle.com/technetwork/articles/javase/index-135205.html#1 Table Sorting and Filtering - New and Updated Desktop Features in Java SE 6, Part 2] -- [[TableRowSorterでJTableのソート>Swing/TableRowSorter]] * 参考リンク [#reference] - [https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#sorting Sorting and Otherwise Manipulating Data - How to Use Tables (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)] - [https://docs.oracle.com/javase/tutorial/uiswing/components/table.html How to Use Tables] - [https://community.oracle.com/thread/1185784 Generics - Simple method but hard with generics: compareTo()] - [https://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableSorterDemoProject/src/components/TableSorter.java TableSorter.java] * コメント [#comment] #comment - いつもお世話になっております。 `jtable`を下記のように初期化します。 -- &user(Tiger); &new{2010-08-05 (木) 06:07:47}; #code{{ // DefaultTableModel model = new DefaultTableModel(); TestModel model = new TestModel(); TableSorter sorter = new TableSorter(model); JTable table = new JTable(sorter); sorter.setTableHeader(table.getTableHeader()); }} - その後、ソートした状態で、一行ずつのデータを取り出した場合、 どうすればよろしいでしょうか?例えば、`No.`欄をソートして、下り順で`No.`欄と`Name`欄のデータを`System.out.println(model.getValueAt(row, 1))`したい場合、その`row`は`sorter`に関連していると思います。 `row=?`かが分かりません。説明下手で、大変申し訳ございません。ご教示をください。よろしくお願い致します。 -- &user(Tiger); &new{2010-08-05 (木) 06:07:47}; -- こんにちは。多分、`sorter.modelIndex(viewIndex);`でいいと思います。 -- &user(aterai); &new{2010-08-05 (木) 13:17:51}; #code{{ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; public class SorterModelIndex { public JComponent makeUI() { String[] columnNames = {"String", "Integer", "Boolean"}; Object[][] data = { {"aaa", 12, true}, {"bbb", 5, false}, {"CCC", 92, true}, {"DDD", 0, false} }; DefaultTableModel model = new DefaultTableModel(data, columnNames) { @Override public Class<?> getColumnClass(int column) { return getValueAt(0, column).getClass(); } }; TableSorter sorter = new TableSorter(model); JTable table = new JTable(sorter); sorter.setTableHeader(table.getTableHeader()); table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { int viewIndex = table.getSelectedRow(); if (!e.getValueIsAdjusting() && viewIndex >= 0) { Object o = model.getValueAt(sorter.modelIndex(viewIndex), 0); System.out.println(o); } } }); JPanel p = new JPanel(new BorderLayout()); p.add(new JScrollPane(table)); return p; } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(); } }); } public static void createAndShowGUI() { JFrame f = new JFrame(); f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); f.getContentPane().add(new SorterModelIndex().makeUI()); f.setSize(320, 240); f.setLocationRelativeTo(null); f.setVisible(true); } } }} - 早速のご回答、ありがとうございました。 選択された行の値を取り出すことができますが、今回表(`jTable`)の内容を`CSV`に書き出そうとしております。即ち選択した行がない場合、ソートをして(上り順`CCC`、`DDD`、`aaa`、`bbb`), `jTable.getValueAt(sorter.modelIndex(i), j);`(`i`:行 `j`:列)、書き出した結果は(`aaa`, `bbb`, `CCC`, `DDD`)。即ち`sorter`していなかったの状態で書き出されました。読みにくいかもしれませんが、ご教示ください。 宜しくお願い致します -- &user(Tiger); &new{2010-08-05 (木) 15:42:51}; -- `JTable`に表示されている見たまま(全選択、KBD{Ctrl+C}でコピーして`TSV`)の状態でということでしょうか。それなら`sorter`は関係なく、以下のように`JTable#getValueAt`メソッドを普通に使えばいいかもしれません(`TableModel#getValueAt`と`JTable#getValueAt`の違いに注意)。 -- &user(aterai); &new{2010-08-05 (木) 17:54:10}; #code{{ p.add(new JButton(new AbstractAction("test") { @Override public void actionPerformed(ActionEvent e) { for (int i = 0; i < table.getRowCount(); i++) { for (int j = 0; j < table.getColumnCount(); j++) { //Object o = table.getValueAt(i, table.convertColumnIndexToView(j)); Object o = table.getValueAt(i, j); System.out.print(o+","); } System.out.print("\n"); } System.out.println("----"); } }), BorderLayout.SOUTH); }} - ありがとうございました。ご指摘の通り、できました。 -- &user(Tiger); &new{2010-08-05 (木) 18:08:42}; - いつもお世話になっております。`JDK1.5`を使っています。`Name`と`Comment`欄をソートするとき、`No.`欄はソートさせないで、固定のままできますか?ご教示をよろしくお願いいたします。 -- &user(Tiger); &new{2010-09-10 (金) 12:41:32}; -- こんにちは。以下のようなレンダラーを使って、表示を`row(View)`にしてしまうのが簡単な気がします(KBD{Ctrl+C}などでコピーすると`Model`の値がコピーされたりしますが…)。 -- &user(aterai); &new{2010-09-10 (金) 14:45:58}; #code{{ TableColumn col = table.getColumnModel().getColumn(0); col.setCellRenderer(new DefaultTableCellRenderer() { @Override public Component getTableCellRendererComponent( JTable table, Object v, boolean isS, boolean hasF, int row, int col) { Component c = super.getTableCellRendererComponent(table, v, isS, hasF, row, col); if (c instanceof JLabel) ((JLabel) c).setText("" + row); return c; } }); }} - ご教示、ありがとうございました。思ったとおりの動きです。 -- &user(Tiger); &new{2010-09-10 (金) 16:32:27}; #comment