Swing/FloatableMenuBar のバックアップ(No.1)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/FloatableMenuBar へ行く。
- 1 (2023-03-20 (月) 21:15:06)
- 2 (2023-03-21 (火) 16:22:09)
- 3 (2024-11-20 (水) 11:18:16)
- category: swing folder: FloatableMenuBar title: JToolBar内にJMenuBarを配置して分離・移動可能に設定する tags: [JToolBar, JMenuBarm, JMenu, JPopupMenu] author: aterai pubdate: 2023-03-20T21:13:17+09:00 description: JToolBar内にJMenuBarを配置することで分離・移動可能なメニューを作成します。 image: https://drive.google.com/uc?id=1DbHuFYcf7KnhBIFnBfL2wvZSudJvLGgd
概要
JToolBar内にJMenuBarを配置することで分離・移動可能なメニューを作成します。
Screenshot
Advertisement
サンプルコード
JMenuBar menuBar = new JMenuBar();
menuBar.add(makeMenu("JMenu 1"));
JMenu menu2 = makeMenu("JMenu 2");
menu2.addMenuListener(new MenuListener() {
private boolean isFloating(JMenu menu) {
Container c = SwingUtilities.getAncestorOfClass(JToolBar.class, menu);
return c instanceof JToolBar &&
!((BasicToolBarUI) ((JToolBar) c).getUI()).isFloating();
}
@Override public void menuSelected(MenuEvent e) {
JMenu menu = (JMenu) e.getSource();
if (menu.isTopLevelMenu() && isFloating(menu)) {
Dimension d = menu.getPreferredSize();
Point p = menu.getLocation();
Component cp = getRootPane().getContentPane();
Point pt = SwingUtilities.convertPoint(menu.getParent(), p, cp);
pt.y += d.height * 2;
if (!cp.getBounds().contains(pt)) {
EventQueue.invokeLater(() -> {
JPopupMenu popup = menu.getPopupMenu();
Rectangle bounds = popup.getBounds();
Point loc = menu.getLocationOnScreen();
// int h = bounds.height + UIManager.getInt("Menu.menuPopupOffsetY");
loc.y -= bounds.height + UIManager.getInt("Menu.menuPopupOffsetY");
popup.setLocation(loc);
});
}
}
}
@Override public void menuDeselected(MenuEvent e) {
// Do nothing
}
@Override public void menuCanceled(MenuEvent e) {
// Do nothing
}
});
menuBar.add(menu2);
JToolBar toolBar = new JToolBar();
toolBar.setLayout(new BorderLayout());
toolBar.add(menuBar);
add(toolBar, BorderLayout.NORTH);
View in GitHub: Java, Kotlin解説
JToolBar
のレイアウトをBorderLayout
に変更してJMenuBar
を追加JToolBar
のデフォルトレイアウトは配置で水平垂直を切り替えるBoxLayout
- この
BoxLayout
のままだとJMenuBar
の幅がJToolBar
の幅まで拡張されない JMenuBar#setMaximumSize(...)
で十分大きな最大サイズを設定すればBoxLayout
のままでも回避可能- このサンプルでは垂直にしてもレイアウトの切り替えは実行しないのでパネルの左右に
JToolBar
を配置不可に設定
MenuListener
をJMenu
に追加してBorderLayout.SOUTH
にJToolBar
が配置されている場合はJMenu
の上方にJPopupMenu
を開くようその位置を変更JMenu
がトップレベル(親がJPopupMenu
ではなくJMenuBar
)、かつJMenuBar
がフローティング状態ではない場合のみ、JPopupMenu
を開く位置を変更するかどうかチェックしている