---
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
---
* Summary [#summary]
クリックするとポップアップメニューを表示する`JToggleButton`を作成し、これをツールバーに追加します。
#download(https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTVg5xIBaI/AAAAAAAAAnw/ds2ybXI2lUE/s800/ToolButtonPopup.png)
* Source Code Examples [#sourcecode]
#code(link){{
class MenuArrowIcon implements Icon {
@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();
}
@Override public int getIconWidth() {
return 9;
}
@Override public int getIconHeight() {
return 9;
}
}
class MenuToggleButton extends JToggleButton {
private static final Icon ARROW_ICON = new MenuArrowIcon();
private JPopupMenu popup;
protected MenuToggleButton() {
this("", null);
}
protected MenuToggleButton(Icon icon) {
this("", icon);
}
protected MenuToggleButton(String text) {
this(text, null);
}
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()));
}
public JPopupMenu getPopupMenu() {
return popup;
}
public void setPopupMenu(JPopupMenu pop) {
this.popup = pop;
pop.addPopupMenuListener(new PopupMenuListener() {
@Override public void popupMenuCanceled(PopupMenuEvent e) {
/* not needed */
}
@Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
/* not needed */
}
@Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
setSelected(false);
}
});
}
@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);
}
}
}}
* Description [#explanation]
* Description [#description]
- `JToggleButton`の右側に余白を設定してそこに下向きの矢印アイコンを描画
- `JToggleButton`に`ActionListener`を追加しクリックすると`JPopupMenu#show(...)`メソッドで`JPopupMenu`を表示
-- `JPopupMenu`の表示位置はクリック位置ではなく`JToggleButton`の下辺になるよう調整
* Reference [#reference]
- [https://xp-style-icons.en.softonic.com/ XP Style Icons - Download]
- [https://community.oracle.com/thread/1375327 Swing - Swing bug? cannot set width of JToggleButton]
* Comment [#comment]
#comment
- いつもお世話になっております。`JToggleButton`を`On/Off`時、背景色を変える方法はありますか?`jToggleButton.setBackground(Color.RED);`で試してみましたが、色変化はありませんでした。ご教示、よろしくお願いいたします -- &user(Panda); &new{2011-04-04 (月) 14:23:21};
- こんばんは。`JToggleButton#setBackground(Color)`は、`LookAndFeel`によっては適用されない場合があります。このため、独自の`ToggleButtonUI`を用意したり、例えば以下のような方法を使用する必要があります。 -- &user(aterai); &new{2011-04-04 (月) 17:15:55};
-- 例`1`: 文字列から背景色、縁などのすべてを含めたアイコンを用意して`setSelectedIcon`で設定する
-- 例`2`: `setContentAreaFilled(false);`として、自前で選択時の背景を描画する
#code{{
JToggleButton button = new JToggleButton("text", icon) {
@Override protected void paintComponent(Graphics g) {
if (getModel().isSelected()) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setColor(getBackground());
g2.fillRoundRect(0, 0, getWidth(), getHeight(), 4, 4);
g2.dispose();
}
super.paintComponent(g);
// ...
}
};
button.setBackground(Color.RED);
button.setContentAreaFilled(false);
}}
#comment