概要

MenuSelectionManagerですべてのJPopupMenuを取得し、任意のタイミングでそれらを非表示に切り替えます。

サンプルコード

tabs.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
    KeyStroke.getKeyStroke(KeyEvent.VK_4, KeyEvent.CTRL_MASK), "next2");
tabs.getActionMap().put("next2", new AbstractAction() {
  @Override public void actionPerformed(ActionEvent e) {
    for (MenuElement m: MenuSelectionManager.defaultManager().getSelectedPath()) {
      if (m instanceof JPopupMenu) {
        ((JPopupMenu) m).setVisible(false);
      }
    }
    tabs.setSelectedIndex((tabs.getSelectedIndex() + 1) % tabs.getTabCount());
  }
});
View in GitHub: Java, Kotlin

解説

  • Ctrl+1: prev1
    • JTableに設定したJPopupMenuを開いた状態でJTabbedPaneに設定したキー入力(JComponent.WHEN_IN_FOCUSED_WINDOW)によるタブ切替アクションを実行するとJPopupMenuが開いたまま前のタブの選択が実行される
    • requestFocusInWindow()などでフォーカスをJTable以外に移動してもJPopupMenuは閉じない
  • Ctrl+2: next1
    • JTableに設定したJPopupMenuを開いた状態(JPopupMenuにフォーカスがある)の場合、JTabbedPaneに設定したキー入力(JComponent.WHEN_FOCUSED)によるタブ切替アクションは実行不可
  • Ctrl+3: prev2
    • JTabbedPaneに設定したキー入力(JComponent.WHEN_IN_FOCUSED_WINDOW)によるタブ切替アクションを実行する場合、直前に自前のマウスプレスイベント発行してすべてのJPopupMenuを閉じる
  • Ctrl+4: next2
    • JTabbedPaneに設定したキー入力(JComponent.WHEN_IN_FOCUSED_WINDOW)によるタブ切替アクションを実行する場合、MenuSelectionManager#getSelectedPath()ですべてのJPopupMenuを取得してJPopupMenu#setVisible(false)で非表示にする
    • 参考: javax/swing/plaf/basic/BasicPopupMenuUI.javaList<JPopupMenu> getPopups()メソッド

  • 以下のようにLayeredPane#getComponentsInLayer(JLayeredPane.POPUP_LAYER)で表示中のJPopupMenuを取得する方法もあるが、親JFrameの外に表示されるHeavyWeightWindowを使用したJPopupMenuが取得できない
    JLayeredPane lp = ((JFrame) tabs.getTopLevelAncestor()).getLayeredPane();
    for (Component c: lp.getComponentsInLayer(JLayeredPane.POPUP_LAYER)) {
      for (Component p: ((Container) c).getComponents()) {
        if (p instanceof JPopupMenu) {
          p.setVisible(false);
        }
      }
    }
    

参考リンク

コメント