JMenuの領域内にマウスカーソルでポップアップメニューを表示する
Total: 5237
, Today: 2
, Yesterday: 1
Posted by aterai at
Last-modified:
概要
JMenu
の領域内にマウスカーソルが入ったときにポップアップメニューが開くように設定します。
Screenshot
Advertisement
サンプルコード
visitAll(menubar, new MouseAdapter() {
@Override public void mousePressed(MouseEvent e) {
if (check.isSelected()) {
((AbstractButton) e.getComponent()).doClick();
}
}
@Override public void mouseEntered(MouseEvent e) {
if (check.isSelected()) {
((AbstractButton) e.getComponent()).doClick();
}
}
});
View in GitHub: Java, Kotlin解説
上記のサンプルでは、トップレベルの(JMenuBar
の子コンポーネントになっている)JMenu
の領域内にマウスカーソルが入った場合に自動的にポップアップメニューが開くように、JMenu#doClick()
を実行するMouseListener
を追加しています。
- マウスボタンを押した場合も入った場合にすでに表示したポップアップメニューが非表示にならないように
JMenu#doClick()
を実行 - このサンプルのすべての
JMenuItem
はbeep
音を鳴らすだけのアクションを設定している - この
JMenu
の入った、JPopupMenu
をJComponent#setComponentPopupMenu(...)
でJMenuBar
以外のコンポーネントに設定すると無限ループする - 回避方法:
- マウスイベントを作成して
menu.dispatchEvent(new MouseEvent(menu, MouseEvent.MOUSE_ENTERED, e.getWhen(), 0, 0, 0, 0, false));
を実行する MenuElement
の配列を作成し、MenuSelectionManager.defaultManager().setSelectedPath(new MenuElement[]{...});
を実行する- ドキュメントには、「このメソッドは public ですが、Look & Feel エンジンで使用されるため、クライアントアプリケーションからは呼び出さないでください。」と記述されているが、現状では
JMenu
のbuildMenuElementArray(...)
が以下の状態なので仕方ない
- ドキュメントには、「このメソッドは public ですが、Look & Feel エンジンで使用されるため、クライアントアプリケーションからは呼び出さないでください。」と記述されているが、現状では
- マウスイベントを作成して
/*
* Build an array of menu elements - from <code>PopupMenu</code> to
* the root <code>JMenuBar</code>.
* @param leaf the leaf node from which to start building up the array
* @return the array of menu items
*/
private MenuElement[] buildMenuElementArray(JMenu leaf) {
Vector<MenuElement> elements = new Vector<MenuElement>();
Component current = leaf.getPopupMenu();
JPopupMenu pop;
JMenu menu;
JMenuBar bar;
while (true) {
if (current instanceof JPopupMenu) {
pop = (JPopupMenu) current;
elements.insertElementAt(pop, 0);
current = pop.getInvoker();
} else if (current instanceof JMenu) {
menu = (JMenu) current;
elements.insertElementAt(menu, 0);
current = menu.getParent();
} else if (current instanceof JMenuBar) {
bar = (JMenuBar) current;
elements.insertElementAt(bar, 0);
MenuElement me[] = new MenuElement[elements.size()];
elements.copyInto(me);
return me;
}
}
}