---
category: swing
folder: RowSorterPopupMenu
title: JTableHeaderにJPopupMenuを追加してソート
tags: [JTable, JTableHeader, JPopupMenu, PopupMenuListener, TableRowSorter]
author: aterai
pubdate: 2009-12-07T14:24:46+09:00
description: JTableHeaderにJPopupMenuを追加してソートします。
image: https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTSY9WWpNI/AAAAAAAAAis/Z0YqvftAIh8/s800/RowSorterPopupMenu.png
---
* Summary [#summary]
`JTableHeader`に`JPopupMenu`を追加してソートします。
#download(https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTSY9WWpNI/AAAAAAAAAis/Z0YqvftAIh8/s800/RowSorterPopupMenu.png)
* Source Code Examples [#sourcecode]
#code(link){{
private class TablePopupMenu extends JPopupMenu {
private final List<SortAction> actions = Arrays.asList(
new SortAction(SortOrder.ASCENDING),
new SortAction(SortOrder.DESCENDING));
// new SortAction(SortOrder.UNSORTED));
public TablePopupMenu() {
super();
for (Action a: actions) {
add(a);
}
}
@Override public void show(Component c, int x, int y) {
if (c instanceof JTableHeader) {
JTableHeader header = (JTableHeader) c;
JTable table = header.getTable();
header.setDraggedColumn(null);
header.repaint();
table.repaint();
int i = table.convertColumnIndexToModel(header.columnAtPoint(new Point(x, y)));
if (i >= 0) {
actions.forEach(a -> a.setIndex(i));
super.show(c, x, y);
}
}
}
}
private class SortAction extends AbstractAction {
private final SortOrder dir;
private int index = -1;
public SortAction(SortOrder dir) {
super(dir.toString());
this.dir = dir;
}
public void setIndex(int index) {
this.index = index;
}
@Override public void actionPerformed(ActionEvent e) {
table.getRowSorter().setSortKeys(Arrays.asList(
new RowSorter.SortKey(index, dir)));
}
}
}}
* Description [#explanation]
* Description [#description]
上記のサンプルでは、マウスカーソルの下にある`JTableHeader`カラムをクリック(`WindowsLookAndFeel`:右クリック)して`JPopupMenu`を表示し、昇順か降順の`JMenuItem`を指定してのソートが可能になっています。デフォルトのカラム左クリックによるソートは`TableRowSorter#toggleSortOrder(...)`をオーバーライドして無効にしています。
- %%ソートに`JTableHeader`のフォーカスペイントをクリアするために以下のような`PopupMenuListener`を追加%%
- 列を右クリックで表示範囲外までドラッグしてからリリースしてポップアップを開くと描画が乱れるので、`JPopupMenu#show(...)`をオーバーライドしてドラッグ状態の解消、ヘッダ、テーブルの再描画を実行
-- `PopupMenuListener`を利用する場合は`popupMenuWillBecomeInvisible`ではなく`popupMenuWillBecomeVisible`でも同様の処理を行う
#code{{
JPopupMenu pop = new TablePopupMenu();
JTableHeader header = table.getTableHeader();
header.setComponentPopupMenu(pop);
pop.addPopupMenuListener(new PopupMenuListener() {
@Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
header.setDraggedColumn(null);
header.repaint();
header.getTable().repaint();
}
@Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// header.setDraggedColumn(null);
header.repaint();
header.getTable().repaint();
}
@Override public void popupMenuCanceled(PopupMenuEvent e) {}
});
}}
* Reference [#reference]
- [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/DefaultRowSorter.html#toggleSortOrder-int- DefaultRowSorter#toggleSortOrder(int) (Java Platform SE 8)]
* Comment [#comment]
#comment
#comment