概要

JPopupMenuのレイアウトを変更することで、上部にメニューボタンを水平に並べて表示します。

サンプルコード

JPopupMenu popup = new JPopupMenu();
GridBagConstraints c = new GridBagConstraints();
popup.setLayout(new GridBagLayout());

c.weightx = 1d;
c.weighty = 0d;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.CENTER;

c.gridy = 0;
popup.add(makeButton("\u21E6"), c);
popup.add(makeButton("\u21E8"), c);
popup.add(makeButton("\u21BB"), c);
popup.add(makeButton("\u2729"), c);

c.insets = new Insets(2, 0, 2, 0);
c.gridwidth = 4;
c.gridx = 0;
c.gridy = GridBagConstraints.RELATIVE;
popup.add(new JSeparator(), c);

c.insets = new Insets(0, 0, 0, 0);
popup.add(new JMenuItem("aaaaaaaaaa"), c);
popup.add(new JPopupMenu.Separator(), c);
popup.add(new JMenuItem("bbbb"), c);
popup.add(new JMenuItem("ccccccccccccccccccccc"), c);
popup.add(new JMenuItem("dddddddddd"), c);
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、JPopupMenuのレイアウトをGridBagLayoutに変更して、上部に4つのメニューボタンを水平に並べて表示します。これらのメニューボタンは、JMenuItemの以下のメソッドをオーバーライドすることでJButton風に表示を変更しています。

  • JMenuItem#paintComponent(...)をオーバーライドして32x32Iconのみを直接描画
    • JMenuItem#setIcon(...)を使用すると文字列の左側にIconが表示される
    • ボタン中央にIconが描画されるように位置を計算する
      • GridBagLayoutGridBagConstraints.HORIZONTALと水平方向に拡張しているためgetSize()で現在のボタンサイズを取得して中央を求める
  • JMenuItem#getPreferredSize()をオーバーライドしてIconのサイズを推奨サイズとして返す
    • JMenuItem#setIcon(...)を使用していないので直接Iconのサイズを渡す必要がある
final Icon icon = new SymbolIcon(symbol);
JMenuItem b = new JMenuItem() {
  private final Dimension d = new Dimension(icon.getIconWidth(), icon.getIconHeight());

  @Override public Dimension getPreferredSize() {
    return d;
  }

  @Override protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Dimension cd = getSize();
    Dimension pd = getPreferredSize();
    int offx = (int) (.5 + .5 * (cd.width  - pd.width));
    int offy = (int) (.5 + .5 * (cd.height - pd.height));
    icon.paintIcon(this, g, offx, offy);
  }
};
b.setOpaque(true);

参考リンク

コメント