TITLE:JToggleButtonからポップアップメニューを開く

JToggleButtonからポップアップメニューを開く

編集者:Terai Atsuhiro~

作成日:2006-07-10
更新日:2022-08-19 (金) 12:21:23
  • category: swing folder: ToolButtonPopup title: JToggleButtonからポップアップメニューを開く tags: [JToggleButton, JPopupMenu, JToolBar, Icon] author: aterai pubdate: 2006-07-10T10:10:27+09:00 description: クリックするとポップアップメニューを表示するJToggleButtonを作成し、これをツールバーに追加します。 image: https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTVg5xIBaI/AAAAAAAAAnw/ds2ybXI2lUE/s800/ToolButtonPopup.png hreflang:
       href: https://java-swing-tips.blogspot.com/2008/12/adding-jpopupmenu-to-jtoolbar-button.html
       lang: en

概要

クリックするとポップアップメニューを表示するJToggleButtonを作成し、これをツールバーに追加します。

概要

クリックするとポップアップメニューを表示するJToggleButtonを作成し、これをツールバーに追加します。

サンプルコード

#spanend
#spanadd
class MenuArrowIcon implements Icon {
#spanend
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setPaint(Color.BLACK);
    g2.translate(x, y);
    g2.drawLine(2, 3, 6, 3);
    g2.drawLine(3, 4, 5, 4);
    g2.drawLine(4, 5, 4, 5);
    g2.dispose();
  }

#spandel
#screenshot
#spanend
  @Override public int getIconWidth()  {
    return 9;
  }

#spandel
**サンプルコード [#o01c8911]
#spanend
 class MenuToggleButton extends JToggleButton {
   private final Icon i = new MenuArrowIcon();
   private final String space;
   public MenuToggleButton(final AbstractAction aa, String space) {
     super(new AbstractAction((String)aa.getValue("Name")+space) {
       public void actionPerformed(ActionEvent ae) {
         aa.actionPerformed(ae);
       }
     });
     this.space = space;
     this.setFocusPainted(false);
   }
   public void paintComponent(Graphics g) {
     super.paintComponent(g);
     Dimension dim = getSize();
     Insets ins = getInsets();
     int h = dim.height;
     int w = SwingUtilities.computeStringWidth(g.getFontMetrics(), space);
     int x = dim.width-ins.right-i.getIconWidth()-(w-i.getIconWidth())/2;
     int y = ins.top+(dim.height-ins.top-ins.bottom-i.getIconHeight())/2;
     i.paintIcon(this, g, x, y);
   }
 }
  @Override public int getIconHeight() {
    return 9;
  }
#spanadd
}
#spanend

-&jnlp;
-&jar;
-&zip;
#spanadd
class MenuToggleButton extends JToggleButton {
#spanend
  private static final Icon ARROW_ICON = new MenuArrowIcon();
  private JPopupMenu popup;

#spandel
**解説 [#i6f6caf9]
#spanend
#spandel
上記のサンプルでは、ボタンの文字列に空白文字を追加することで右側にスペースを取得し、ここに下向きの矢印を上書きしています。
#spanend
  protected MenuToggleButton() {
    this("", null);
  }

#spandel
**参考リンク [#f95e2567]
#spanend
-[[XP Style Icons - Windows Application Icon, Software XP Icons>http://www.icongalore.com/]]
--アイコンを利用しています。
-[[Swing bug? cannot set width of JToggleButton>http://forum.java.sun.com/thread.jspa?threadID=791450]]
  protected MenuToggleButton(Icon icon) {
    this("", icon);
  }

#spandel
**コメント [#h4a49a4d]
#spanend
  protected MenuToggleButton(String text) {
    this(text, null);
  }
#spanadd

#spanend
  protected MenuToggleButton(String text, Icon icon) {
    super();
    Action action = new AbstractAction(text) {
      @Override public void actionPerformed(ActionEvent e) {
        Component b = (Component) e.getSource();
        Optional.ofNullable(getPopupMenu()).ifPresent(p -> p.show(b, 0, b.getHeight()));
      }
    };
    action.putValue(Action.SMALL_ICON, icon);
    setAction(action);
    setFocusable(false);
    setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4 + ARROW_ICON.getIconWidth()));
  }
#spanadd

#spanend
  public JPopupMenu getPopupMenu() {
    return popup;
  }
#spanadd

#spanend
  public void setPopupMenu(JPopupMenu pop) {
    this.popup = pop;
    pop.addPopupMenuListener(new PopupMenuListener() {
      @Override public void popupMenuCanceled(PopupMenuEvent e) {
        /* not needed */
      }
#spanadd

#spanend
      @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
        /* not needed */
      }
#spanadd

#spanend
      @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
        setSelected(false);
      }
    });
  }
#spanadd

#spanend
  @Override protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Dimension dim = getSize();
    Insets ins = getInsets();
    int x = dim.width - ins.right;
    int y = ins.top + (dim.height - ins.top - ins.bottom - ARROW_ICON.getIconHeight()) / 2;
    ARROW_ICON.paintIcon(this, g, x, y);
  }
#spanadd
}
#spanend
#spanadd
View in GitHub: Java, Kotlin

解説

  • JToggleButtonの右側に余白を設定してそこに下向きの矢印アイコンを描画
  • JToggleButtonActionListenerを追加しクリックするとJPopupMenu#show(...)メソッドでJPopupMenuを表示
    • JPopupMenuの表示位置はクリック位置ではなくJToggleButtonの下辺になるよう調整

参考リンク

コメント