JTableHeaderにJPopupMenuを追加してソート
Total: 7001
, Today: 1
, Yesterday: 0
Posted by aterai at
Last-modified:
概要
JTableHeader
にJPopupMenu
を追加してソートします。
Screenshot
Advertisement
サンプルコード
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)));
}
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、マウスカーソルの下にあるJTableHeader
カラムをクリック(WindowsLookAndFeel
:右クリック)してJPopupMenu
を表示し、昇順か降順のJMenuItem
を指定してのソートが可能になっています。デフォルトのカラム左クリックによるソートはTableRowSorter#toggleSortOrder(...)
をオーバーライドして無効にしています。
ソートにJTableHeader
のフォーカスペイントをクリアするために以下のようなPopupMenuListener
を追加- 列を右クリックで表示範囲外までドラッグしてからリリースしてポップアップを開くと描画が乱れるので、
JPopupMenu#show(...)
をオーバーライドしてドラッグ状態の解消、ヘッダ、テーブルの再描画を実行PopupMenuListener
を利用する場合はpopupMenuWillBecomeInvisible
ではなくpopupMenuWillBecomeVisible
でも同様の処理を行う
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) {}
});