Swing/RightClickRowSelectionAndPopupMenu のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/RightClickRowSelectionAndPopupMenu へ行く。
- 1 (2023-11-06 (月) 01:48:28)
- 2 (2023-11-10 (金) 19:28:16)
- category: swing folder: RightClickRowSelectionAndPopupMenu title: JTableの行を右クリックで選択して同時にJPopupMenuを開く tags: [JTable, JPopupMenu, MouseListener, PopupMenuListener, JLayer] author: aterai pubdate: 2023-11-06T01:41:53+09:00 description: JTableの行を右クリックした場合、その選択状態の変更とJPopupMenuの表示を両方実行する方法をテストします。 image: https://drive.google.com/uc?id=1dB25osj9KkSJRo10xdTA9IJhMoHz3Fm0
概要
JTable
の行を右クリックした場合、その選択状態の変更とJPopupMenu
の表示を両方実行する方法をテストします。
Screenshot
Advertisement
サンプルコード
class RightMouseButtonLayerUI extends LayerUI<JScrollPane> {
@Override public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
}
}
@Override public void uninstallUI(JComponent c) {
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(0);
}
super.uninstallUI(c);
}
@Override protected void processMouseEvent(
MouseEvent e, JLayer<? extends JScrollPane> l) {
Component c = e.getComponent();
if (c instanceof JTable && SwingUtilities.isRightMouseButton(e)) {
JTable table = (JTable) c;
if (table.isEditing()) {
table.removeEditor();
}
Point pt = e.getPoint();
Rectangle r = TableUtils.getCellArea(table);
if (r.contains(pt)) {
int currentRow = table.rowAtPoint(pt);
int currentColumn = table.columnAtPoint(pt);
if (TableUtils.isNotRowContains(table.getSelectedRows(), currentRow)) {
table.changeSelection(currentRow, currentColumn, false, false);
}
} else {
table.clearSelection();
}
} else {
super.processMouseEvent(e, l);
}
}
}
final class TableUtils {
private TableUtils() {
/* Singleton */
}
public static Rectangle getCellArea(JTable table) {
Rectangle start = table.getCellRect(0, 0, true);
int rc = table.getRowCount();
int cc = table.getColumnCount();
Rectangle end = table.getCellRect(rc - 1, cc - 1, true);
return start.union(end);
}
public static boolean isNotRowContains(int[] selectedRows, int currentRow) {
for (int i : selectedRows) {
if (i == currentRow) {
return false;
}
}
return true;
}
}
View in GitHub: Java, Kotlin解説
Default
- デフォルトのマウスクリックによる
JTable
の行選択では!SwingUtilities.isLeftMouseButton(MouseEvent)
で左クリック以外は無視される - このため右クリックでは行の選択状態は変更されない
- デフォルトのマウスクリックによる
MouseListener
JTable
にMouseListener
を追加してmousePressed(...)
をオーバーライドし、JPopupMenu
を開く動作はそのまま残して別途右クリックでの選択状態変更動作を定義JTable
が編集状態の場合はJTable#removeEditor()
を実行してそれをキャンセルJTable
のセル領域以外で右クリックされた場合はJTable#clearSelection()
を実行して選択状態をクリアし、JPopupMenu
を開くJTable
の行選択領域内で右クリックされた場合は選択状態を維持したままJPopupMenu
を開くJTable
のセル領域かつ行選択領域外で右クリックされた場合は右クリックされた行のみを選択状に変更し、JPopupMenu
を開く
- 制限:
JPopupMenu
が開いた状態のまま連続して右クリックするとMouseListener#mousePressed(...)
が実行されないため、JPopupMenu
は右クリックした位置に再オープンされるが行選択状態は変更できない
PopupMenuListener
JPopupMenu
にPopupMenuListener
を追加してpopupMenuWillBecomeVisible(PopupMenuEvent)
をオーバーライドし、JPopupMenu
を開く動作はそのまま残して別途右クリックでの選択状態変更動作を定義- 右クリックで実行する動作の定義は
MouseListener
と同様
- 右クリックで実行する動作の定義は
- 制限:
JPopupMenu
の左上隅を右クリックされた位置として使用するため、画面端などでJPopupMenu
の表示位置が調整される場合は右クリックされた行が選択されない場合がある
JLayer
JTable
の親JScrollPane
をJLayer
でラップしてprocessMouseEvent(...)
をオーバーライドし、JPopupMenu
を開く動作はそのまま残して別途右クリックでの選択状態変更動作を定義- 右クリックで実行する動作の定義は
MouseListener
と同様
- 右クリックで実行する動作の定義は