概要

JMenuBarのレイアウトを垂直BoxLayoutに変更してJMenuを垂直方向に並べて配置するサイドバーを作成します。

サンプルコード

JMenuBar menuBar = new JMenuBar() {
  @Override public void updateUI() {
    super.updateUI();
    setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    // setLayout(new GridLayout(0, 1, 2, 2));
    setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
  }
};
initMenuBar(menuBar);
MenuListener listener = new MenuListener() {
  @Override public void menuSelected(MenuEvent e) {
    Object src = e.getSource();
    if (src instanceof JMenu && ((JMenu) src).isTopLevelMenu()) {
      EventQueue.invokeLater(() -> {
        JMenu menu = (JMenu) src;
        Point loc = menu.getLocationOnScreen();
        loc.x += menu.getWidth();
        menu.getPopupMenu().setLocation(loc);
      });
    }
  }

  @Override public void menuDeselected(MenuEvent e) {
    // Do nothing
  }

  @Override public void menuCanceled(MenuEvent e) {
    // Do nothing
  }
};
for (MenuElement m : menuBar.getSubElements()) {
  if (m instanceof JMenu) {
    JMenu menu = (JMenu) m;
    menu.addMenuListener(listener);
    Dimension d = menu.getMaximumSize();
    d.width = Short.MAX_VALUE;
    menu.setMaximumSize(d);
  }
}
View in GitHub: Java, Kotlin

解説

  • JMenuBar#setLayout(new BoxLayout(this, BoxLayout.Y_AXIS))してJMenuBarのレイアウトを水平BoxLayoutから垂直BoxLayoutに変更
    • BoxLayoutでリスト状に並べる
    • JSeparatorなどを使用せず、縦JMenuBarのすべての子Componentの高さが同じでよい場合は、JMenuBar#setLayout(new GridLayout(0, 1))JMenuBarのレイアウトを行数指定なしで1列のグリッドに変更する方法もある
  • JMenuBarの子MenuElementでトップレベルJMenuJMenuBar#getSubElements()で取得し、そのJMenuが開くJPopupMenuの表示位置を修正するMenuListenerを追加

参考リンク

コメント