• 追加された行はこの色です。
  • 削除された行はこの色です。
---
category: swing
folder: StayOpenCheckBoxMenuItem
title: JCheckBoxMenuItemをクリックしてもJPopupMenuを閉じないように設定する
tags: [JCheckBoxMenuItem, JCheckBox, JPopupMenu]
author: aterai
pubdate: 2016-02-01T01:14:27+09:00
description: JPopupMenuにクリックしてもポップアップが開いたままの状態を維持するように設定したJCheckBoxMenuItemやJCheckBoxを追加します。
image: https://lh3.googleusercontent.com/-hje86Y7xU8k/Vq4umT64DuI/AAAAAAAAOMs/N6gysnrA3e4/s800-Ic42/StayOpenCheckBoxMenuItem.png
hreflang:
    href: https://java-swing-tips.blogspot.com/2016/05/keep-visible-jpopupmenu-while-clicking.html
    lang: en
---
* 概要 [#f0722069]
JPopupMenuにクリックしてもポップアップが開いたままの状態を維持するように設定したJCheckBoxMenuItemやJCheckBoxを追加します。
* 概要 [#summary]
`JPopupMenu`にクリックしてもポップアップが開いたままの状態を維持するように設定した`JCheckBoxMenuItem`や`JCheckBox`を追加します。

#download(https://lh3.googleusercontent.com/-hje86Y7xU8k/Vq4umT64DuI/AAAAAAAAOMs/N6gysnrA3e4/s800-Ic42/StayOpenCheckBoxMenuItem.png)

* サンプルコード [#na4cab44]
* サンプルコード [#sourcecode]
#code(link){{
JMenuItem mi = new JMenuItem(" ");
mi.setLayout(new BorderLayout());
mi.add(new JCheckBox(title) {
  private transient MouseAdapter handler;
  @Override public void updateUI() {
    removeMouseListener(handler);
    removeMouseMotionListener(handler);
    super.updateUI();
    handler = new DispatchParentHandler();
    addMouseListener(handler);
    addMouseMotionListener(handler);
    setFocusable(false);
    setOpaque(false);
  }
});
popup.add(mi);

popup.add(new JCheckBoxMenuItem("keeping open #2") {
  @Override public void updateUI() {
    super.updateUI();
    setUI(new BasicCheckBoxMenuItemUI() {
      //http://stackoverflow.com/questions/3759379/how-to-prevent-jpopupmenu-disappearing-when-checking-checkboxes-in-it
      @Override protected void doClick(MenuSelectionManager msm) {
        //super.doClick(msm);
        // super.doClick(msm);
        System.out.println("MenuSelectionManager: doClick");
        menuItem.doClick(0);
      }
    });
  }
});
}}

* 解説 [#o3d8ceda]
* 解説 [#explanation]
- `JCheckBox`
-- `JPopupMenu`に`JCheckBox`を追加
-- クリックしてもポップアップは閉じないが、カーソルが乗ってもハイライトされない
-- クリックしてもポップアップは閉じないが、マウスカーソルが乗ってもハイライト表示されない
- `JMenuItem + JCheckBox`
-- `JCheckBox`を配置した`JMenuItem`を作成して`JPopupMenu`に追加
-- `JCheckBox`へのマウスイベント(`mouseMoved`など)を親の`JMenuItem`に転送してハイライトは描画されるが、クリックイベント(`mouseClicked`など)はブロックしてポップアップは閉じないように設定
-- `JCheckBox`を配置したタイトルが空の`JMenuItem`を作成して`JPopupMenu`に追加
-- `JCheckBox`へのマウスイベント(`MOUSE_DRAGGED`, `MOUSE_ENTERED`, `MOUSE_EXITED`, `MOUSE_MOVED`)を親の`JMenuItem`に転送してハイライトを描画
-- `JCheckBox`へのマウスクリックイベント(`MOUSE_CLICKED`, `MOUSE_PRESSED`, `MOUSE_RELEASED`など)はブロックしてポップアップは閉じないように設定
- `JCheckBoxMenuItem`
-- デフォルトの`JCheckBoxMenuItem`で、クリックするとポップアップは閉じる
-- デフォルトの`JCheckBoxMenuItem`をクリックするとポップアップは閉じる
- `keeping open #1`
-- `JCheckBoxMenuItem`に`Action`を追加して、クリック後にポップアップを再度開くように設定
-- `JPopupMenu`が`JFrame`の外に表示される場合は、ポップアップが一瞬消える
-- `JCheckBoxMenuItem`に`Action`を追加してクリック後にポップアップを再度開くように設定
-- `JPopupMenu`が`JFrame`の外に表示される場合はポップアップが一瞬消える
- `keeping open #2`
-- `JCheckBoxMenuItem`に`BasicCheckBoxMenuItemUI#doClick(MenuSelectionManager)`メソッドをオーバーライドした`CheckBoxMenuItemUI`を設定し、クリック後にポップアップを閉じない
--- 代わりに、`menuItem.doClick(0);`でチェック状態のみ変更する
--- 参考: [http://stackoverflow.com/questions/3759379/how-to-prevent-jpopupmenu-disappearing-when-checking-checkboxes-in-it swing - How to prevent JPopUpMenu disappearing when checking checkboxes in it? - Stack Overflow]
-- `JPopupMenu`が`JFrame`の外に表示される場合は、ポップアップが一瞬消える
-- `JCheckBoxMenuItem`に`BasicCheckBoxMenuItemUI#doClick(MenuSelectionManager)`メソッドをオーバーライドした`CheckBoxMenuItemUI`を設定
--- このイベントでクリック後にポップアップを閉じない代わりに`menuItem.doClick(0);`でチェック状態のみ変更する
--- 参考: [https://stackoverflow.com/questions/3759379/how-to-prevent-jpopupmenu-disappearing-when-checking-checkboxes-in-it swing - How to prevent JPopUpMenu disappearing when checking checkboxes in it? - Stack Overflow]

* 参考リンク [#h07389b0]
- [http://stackoverflow.com/questions/3759379/how-to-prevent-jpopupmenu-disappearing-when-checking-checkboxes-in-it swing - How to prevent JPopUpMenu disappearing when checking checkboxes in it? - Stack Overflow]
----
- `Java 9`では、%%`menuItem.putClientProperty("CheckBoxMenuItem.closeOnMouseClick", false);`%% `menuItem.putClientProperty("CheckBoxMenuItem.doNotCloseOnMouseClick", true);`などと設定することで、対象の`JCheckBoxMenuItem`をクリックしても親の`JPopupMenu`は閉じなくなる
-- `UIManager.put("CheckBoxMenuItem.doNotCloseOnMouseClick", true)`で全体の`JCheckBoxMenuItem`に適用可能
-- 参考: [https://bugs.openjdk.org/browse/JDK-8165234 JDK-8165234 Provide a way to not close toggle menu items on mouse click on component level - Java Bug System]

* コメント [#n05a9053]
* 参考リンク [#reference]
- [https://stackoverflow.com/questions/3759379/how-to-prevent-jpopupmenu-disappearing-when-checking-checkboxes-in-it swing - How to prevent JPopUpMenu disappearing when checking checkboxes in it? - Stack Overflow]

* コメント [#comment]
#comment
#comment