Swing/TableSorter のバックアップの現在との差分(No.1)
TITLE:TableSorterでJTableをソート
TableSorterでJTableをソート
編集者:Terai Atsuhiro~
作成日:2005-02-28
更新日:2021-09-24 (金) 14:49:24
概要
JDK 1.5.0
以前に、The Java™ Tutorial
に存在したTableSorter.java
を使用して、JTable
の行を降順、昇順、初期状態にソートします。
Screenshot
Advertisement
概要
TableSorter.javaを利用して、JTableの行を降順、昇順、初期状態にソートします。サンプルコード
#spanend
#spanadd
// DefaultTableModel model = new DefaultTableModel();
#spanend
#spanadd
TestModel model = new TestModel();
#spanend
#spanadd
TableSorter sorter = new TableSorter(model);
#spanend
#spanadd
JTable table = new JTable(sorter);
#spanend
#spanadd
sorter.setTableHeader(table.getTableHeader());
#spanend
#spanadd
View in GitHub: Java, Kotlin解説
The Java™ Tutorial
版のTableSorter
を使用して、JTableのソートで使用しているものと同じTableModel
をソートしています。
#screenshot
-
TableSorter
にはCtrlキーを押しながらヘッダをクリックすると、そのカラムを第2
キー、第3
キーとしてソートする機能もある -
JDK 1.5.0
でGenerics
の警告を出さないようにするにはTableSorter.java
に以下のような修正が必要
サンプルコード
//DefaultTableModel model = new DefaultTableModel(); TestModel model = new TestModel(); TableSorter sorter = new TableSorter(model); JTable table = new JTable(sorter); sorter.setTableHeader(table.getTableHeader());
#spanend
#spanadd
private static class ComparableComparator implements Comparator {
#spanend
@SuppressWarnings("unchecked")
public int compare(Object o1, Object o2) {
return ((Comparable) o1).compareTo(o2);
}
#spanadd
}
#spanend
-&jnlp;
-&jar;
-&zip;
#spanadd
public static final ComparableComparator COMPARABLE_COMAPRATOR
#spanend
= new ComparableComparator();
#spanadd
public static final ComparableComparator LEXICAL_COMPARATOR
#spanend
= new ComparableComparator() {
@SuppressWarnings("unchecked")
public int compare(Object o1, Object o2) {
return o1.toString().compareTo(o2.toString());
}
#spanadd
};
#spanend
#spanadd
private TableModelListener tableModelListener;
#spanend
#spanadd
private Map<Class, Comparator> columnComparators = new HashMap<>();
#spanend
#spanadd
private List<Directive> sortingColumns = new ArrayList<>();
#spanend
#spandel
**解説 [#h8a583cb]
#spanend
#spandel
The JavaTM Tutorial版のTableSorterを使用して、[[JTableのソート>Swing/SortableTable]]で使用しているものと同じTableModelでソートしています。
#spanend
#spanadd
protected ComparableComparator getComparator(int column) {
#spanend
Class columnType = tableModel.getColumnClass(column);
ComparableComparator comparator
= (ComparableComparator) columnComparators.get(columnType);
if (comparator != null) {
return comparator;
}
#spanadd
// ...
#spanend
#spanadd
private class Row implements Comparable<Row> {
#spanend
private int modelIndex;
public Row(int index) {
this.modelIndex = index;
}
public int compareTo(Row o) {
int row1 = modelIndex;
int row2 = o.modelIndex;
#spanadd
// ...
#spanend
#spanadd
The JavaTM Tutorial版のTableSorterには、Ctrlキーを押しながらヘッダをクリックすると、そのカラムを第二キーとしてソートする機能もあります。
- -
-
LookAndFeel
を動作中に切り替える場合は、sorter.setTableHeader(table.getTableHeader());
で設定したJTableHeader
を新しいLookAndFeel
を適用したものに入れ替えておかないとNullPointerException
が発生する
#spanend
#spanadd
private final TableSorter sorter = new TableSorter(model);
#spanend
#spanadd
private final JTable table = new JTable(sorter) {
#spanend
@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();
}
});
}
#spanadd
};
#spanend
#spanadd
1.5でGenericsの警告を出さないようにするには、TableSorter.javaに、以下のような修正を加えれば良いようです(あまりテストしていません)。
- -
-
JDK 1.6.0
からJTable
には標準でソート機能が追加された
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()); } };
参考リンク
- Sorting and Otherwise Manipulating Data - How to Use Tables (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)
- How to Use Tables
- Generics - Simple method but hard with generics: compareTo()
- TableSorter.java
private TableModelListener tableModelListener; private Map<Class, Comparator> columnComparators = new HashMap<Class, Comparator>(); private List<Directive> sortingColumns = new ArrayList<Directive>();
コメント
- いつもお世話になっております。
jtable
を下記のように初期化します。 -- Tiger
protected ComparableComparator getComparator(int column) { Class columnType = tableModel.getColumnClass(column); ComparableComparator comparator = (ComparableComparator) columnComparators.get(columnType); if (comparator != null) { return comparator; }
#spanend
#spanadd
// DefaultTableModel model = new DefaultTableModel();
#spanend
#spanadd
TestModel model = new TestModel();
#spanend
#spanadd
TableSorter sorter = new TableSorter(model);
#spanend
#spanadd
JTable table = new JTable(sorter);
#spanend
#spanadd
sorter.setTableHeader(table.getTableHeader());
#spanend
#spanadd
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;
- その後、ソートした状態で、一行ずつのデータを取り出した場合、 どうすればよろしいでしょうか?例えば、
No.
欄をソートして、下り順でNo.
欄とName
欄のデータをSystem.out.println(model.getValueAt(row, 1))
したい場合、そのrow
はsorter
に関連していると思います。row=?
かが分かりません。説明下手で、大変申し訳ございません。ご教示をください。よろしくお願い致します。 -- Tiger- こんにちは。多分、
sorter.modelIndex(viewIndex);
でいいと思います。 -- aterai
- こんにちは。多分、
#spanend
#spanadd
import java.awt.*;
#spanend
#spanadd
import java.awt.event.*;
#spanend
#spanadd
import javax.swing.*;
#spanend
#spanadd
import javax.swing.event.*;
#spanend
#spanadd
import javax.swing.table.*;
#spanend
#spanadd
public class SorterModelIndex {
#spanend
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);
}
}
});
#spandel
**参考リンク [#f1d425ba]
#spanend
-[[Sorting and Otherwise Manipulating Data - How to Use Tables (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)>http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#sorting]]
-[[How to Use Tables>http://java.sun.com/docs/books/tutorial/uiswing/components/table.html]]
-[[Java Technology Forums - Simple method but hard with generics: compareTo()>http://forum.java.sun.com/thread.jspa?threadID=598815]]
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);
}
#spanadd
}
#spanend
#spanadd
コメント
- 早速のご回答、ありがとうございました。 選択された行の値を取り出すことができますが、今回表(
jTable
)の内容をCSV
に書き出そうとしております。即ち選択した行がない場合、ソートをして(上り順CCC
、DDD
、aaa
、bbb
),jTable.getValueAt(sorter.modelIndex(i), j);
(i
:行j
:列)、書き出した結果は(aaa
,bbb
,CCC
,DDD
)。即ちsorter
していなかったの状態で書き出されました。読みにくいかもしれませんが、ご教示ください。 宜しくお願い致します -- Tiger-
JTable
に表示されている見たまま(全選択、Ctrl+CでコピーしてTSV
)の状態でということでしょうか。それならsorter
は関係なく、以下のようにJTable#getValueAt
メソッドを普通に使えばいいかもしれません(TableModel#getValueAt
とJTable#getValueAt
の違いに注意)。 -- aterai
-
#spanend
#spanadd
p.add(new JButton(new AbstractAction("test") {
#spanend
@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("----");
}
#spanadd
}), BorderLayout.SOUTH);
#spanend
#spanadd
- ありがとうございました。ご指摘の通り、できました。 -- Tiger
- いつもお世話になっております。
JDK1.5
を使っています。Name
とComment
欄をソートするとき、No.
欄はソートさせないで、固定のままできますか?ご教示をよろしくお願いいたします。 -- Tiger- こんにちは。以下のようなレンダラーを使って、表示を
row(View)
にしてしまうのが簡単な気がします(Ctrl+CなどでコピーするとModel
の値がコピーされたりしますが…)。 -- aterai
- こんにちは。以下のようなレンダラーを使って、表示を
#spanend
#spanadd
TableColumn col = table.getColumnModel().getColumn(0);
#spanend
#spanadd
col.setCellRenderer(new DefaultTableCellRenderer() {
#spanend
@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;
}
#spanadd
});
#spanend
#spanadd
- ご教示、ありがとうございました。思ったとおりの動きです。 -- Tiger