• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JPopupMenuをボタンの長押しで表示
#navi(../)
#tags()
RIGHT:Posted by &author(aterai); at 2009-01-26
*JPopupMenuをボタンの長押しで表示 [#m55da14e]
JToolBarに、長押しでJPopupMenu、クリックで選択されたメニューを表示するボタンを追加します。
---
category: swing
folder: PressAndHoldButton
title: JPopupMenuをボタンの長押しで表示
tags: [JToolBar, JButton, JPopupMenu, MouseListener, GridLayout, Timer]
author: aterai
pubdate: 2009-01-26T13:29:29+09:00
description: JToolBarに、長押しでJPopupMenu、クリックで選択されたメニューを表示するボタンを追加します。
image: https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTRIzHMLNI/AAAAAAAAAgs/0_PwsyZOl-I/s800/PressAndHoldButton.png
hreflang:
    href: https://java-swing-tips.blogspot.com/2014/03/long-pressing-jbutton-to-get-jpopupmenu.html
    lang: en
---
* 概要 [#summary]
`JToolBar`に、長押しで`JPopupMenu`、クリックで選択されたメニューを表示するボタンを追加します。

-&jnlp;
-&jar;
-&zip;
#download(https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTRIzHMLNI/AAAAAAAAAgs/0_PwsyZOl-I/s800/PressAndHoldButton.png)

//#screenshot
#ref(http://lh4.ggpht.com/_9Z4BYR88imo/TQTRIzHMLNI/AAAAAAAAAgs/0_PwsyZOl-I/s800/PressAndHoldButton.png)

**サンプルコード [#n8b1ddb4]
* サンプルコード [#sourcecode]
#code(link){{
private class ArrowButtonHandler extends AbstractAction implements MouseListener {
  private final javax.swing.Timer autoRepeatTimer;
  private AbstractButton arrowButton = null;
  public ArrowButtonHandler() {
    autoRepeatTimer = new javax.swing.Timer(1000, new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        System.out.println("InitialDelay(1000)");
        if(arrowButton!=null && arrowButton.getModel().isPressed()
                             && autoRepeatTimer.isRunning()) {
          autoRepeatTimer.stop();
          pop.show(arrowButton, 0, arrowButton.getHeight());
          pop.requestFocusInWindow();
        }
class PressAndHoldHandler extends AbstractAction implements MouseListener {
  public final JPopupMenu pop = new JPopupMenu();
  public final ButtonGroup bg = new ButtonGroup();
  private AbstractButton arrowButton;
  private final Timer holdTimer = new Timer(1000, new ActionListener() {
    @Override public void actionPerformed(ActionEvent e) {
      System.out.println("InitialDelay(1000)");
      if (arrowButton != null && arrowButton.getModel().isPressed()
          && holdTimer.isRunning()) {
        holdTimer.stop();
        pop.show(arrowButton, 0, arrowButton.getHeight());
        pop.requestFocusInWindow();
      }
    });
    autoRepeatTimer.setInitialDelay(1000);
    pop.addPopupMenuListener(new PopupMenuListener() {
      @Override public void popupMenuCanceled(PopupMenuEvent e) {}
      @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}
      @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
        if(arrowButton!=null) {
          arrowButton.setSelected(false);
    }
  });

  public PressAndHoldHandler() {
    super();
    holdTimer.setInitialDelay(1000);
    pop.setLayout(new GridLayout(0, 3, 5, 5));
    for (MenuContext m: makeMenuList()) {
      AbstractButton b = new JRadioButton(m.command);
      b.setActionCommand(m.command);
      b.setForeground(m.color);
      b.setBorder(BorderFactory.createEmptyBorder());
      b.addActionListener(new ActionListener() {
        @Override public void actionPerformed(ActionEvent e) {
          System.out.println(bg.getSelection().getActionCommand());
          pop.setVisible(false);
        }
      }
    });
      });
      pop.add(b);
      bg.add(b);
    }
  }

  private List<MenuContext> makeMenuList() {
    return Arrays.asList(
      new MenuContext("BLACK", Color.BLACK),
      new MenuContext("BLUE", Color.BLUE),
      new MenuContext("CYAN", Color.CYAN),
      new MenuContext("GREEN", Color.GREEN),
      new MenuContext("MAGENTA", Color.MAGENTA),
      new MenuContext("ORANGE", Color.ORANGE),
      new MenuContext("PINK", Color.PINK),
      new MenuContext("RED", Color.RED),
      new MenuContext("YELLOW", Color.YELLOW));
  }

  @Override public void actionPerformed(ActionEvent e) {
    if(autoRepeatTimer.isRunning()) {
      System.out.println("actionPerformed");
      System.out.println("  "+bg.getSelection().getActionCommand());
      if(arrowButton!=null) arrowButton.setSelected(false);
      autoRepeatTimer.stop();
    System.out.println("actionPerformed");
    if (holdTimer.isRunning()) {
      ButtonModel model = bg.getSelection();
      if (model != null) {
        System.out.println(model.getActionCommand());
      }
      holdTimer.stop();
    }
  }

  @Override public void mousePressed(MouseEvent e) {
    System.out.println("mousePressed");
    if(SwingUtilities.isLeftMouseButton(e) && e.getComponent().isEnabled()) {
      arrowButton = (AbstractButton)e.getSource();
      autoRepeatTimer.start();
    Component c = e.getComponent();
    if (SwingUtilities.isLeftMouseButton(e) && c.isEnabled()) {
      arrowButton = (AbstractButton) c;
      holdTimer.start();
    }
  }

  @Override public void mouseReleased(MouseEvent e) {
    autoRepeatTimer.stop();
    holdTimer.stop();
  }

  @Override public void mouseExited(MouseEvent e) {
    if(autoRepeatTimer.isRunning()) {
      autoRepeatTimer.stop();
    if (holdTimer.isRunning()) {
      holdTimer.stop();
    }
  }
  @Override public void mouseEntered(MouseEvent e) {}
  @Override public void mouseClicked(MouseEvent e) {}

  @Override public void mouseEntered(MouseEvent e) {
    /* not needed */
  }

  @Override public void mouseClicked(MouseEvent e) {
    /* not needed */
  }
}
}}

**解説 [#m649a122]
上記のサンプルでは、1000ミリ秒ボタンを押したままにしておくと、JRadioButtonを配置したJPopupMenuを表示します。普通にクリックした場合は、現在選択されているJRadioButtonの色をコンソールに出力するようになっています。
* 解説 [#explanation]
- 長押し
-- ボタンクリックが`1000`ミリ秒以上継続すると`JRadioButton`を配置した`JPopupMenu`を表示
--- `JPopupMenu`のレイアウトを`pop.setLayout(new GridLayout(0, 3))`で変更し`JRadioButton`を`3`列並べて表示
- シングルクリック
-- 現在選択されている`JRadioButton`の色をコンソールに出力

----
JPopupMenuのレイアウトをpop.setLayout(new GridLayout(0,3));で変更し、三列にJRadioButtonを並べています。
* 参考リンク [#reference]
- [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/Timer.html#setInitialDelay-int- Timer#setInitialDelay(...) (Java Platform SE 8)]

//**参考リンク
**コメント [#b93295c6]
* コメント [#comment]
#comment
#comment