TITLE:TableSorterでJTableをソート

Posted by terai at 2005-02-28

TableSorterでJTableをソート

TableSorter.javaを利用して、JTableの行を降順、昇順、初期状態にソートします。以下のサンプルは、以前Tutorialにあった*1TableSorter.javaを使用しています。The JavaTM TutorialのSorting and Otherwise Manipulating Data - How to Use Tables (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)から、TableSorter.java*2を使用しています。

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

#screenshot

サンプルコード

//DefaultTableModel model = new DefaultTableModel();
TestModel model = new TestModel();
TableSorter sorter = new TableSorter(model);
JTable table = new JTable(sorter);
sorter.setTableHeader(table.getTableHeader());

解説

The JavaTM Tutorial版のTableSorterを使用して、JTableのソートで使用しているものと同じTableModelでソートしています。

The JavaTM Tutorial版のTableSorterには、Ctrlキーを押しながらヘッダをクリックすると、そのカラムを第二キーとしてソートする機能もあります。

Java version 1.4.xとWindows XPの環境で、ヘッダにカーソルを置いてもロールオーバーしない場合があるようです。上記のスクリーンショットはJava version 1.5.0_01 で撮っています。

1.5でGenericsの警告を出さないようにするには、TableSorter.javaに、以下のような修正を加えれば良いようです。ただし、まだ@SuppressWarnings("unchecked")があったり、テストも不十分です。

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<Class, Comparator>();
private List<Directive> sortingColumns = new ArrayList<Directive>();

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;
//......

Java SE 6 では、JTable標準で簡単にソート機能を追加することができます(SORTING AND FILTERING TABLESTableRowSorterでJTableのソート)。

参考リンク

コメント

  • いつもお世話になっております。 jtableを下記のように初期化します。
    //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=?かが分かりません。説明下手で、大変申し訳ございません。ご教示をください。よろしくお願い致します。 -- Tiger
    • こんにちは。多分、sorter.modelIndex(viewIndex);でいいと思います。 -- terai
      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}
          };
          final DefaultTableModel model = new DefaultTableModel(data, columnNames) {
            @Override public Class<?> getColumnClass(int column) {
              return getValueAt(0, column).getClass();
            }
          };
          final TableSorter sorter = new TableSorter(model);
          final 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);
        }
      }