• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JComboBoxを使ってポップアップメニューをスクロール
#navi(../)
#tags(BasicComboPopup, JTextPane, JComboBox)
RIGHT:Posted by &author(aterai); at 2005-10-17
*JComboBoxを使ってポップアップメニューをスクロール [#cc8b9df3]
``JComboBox``を使ってスクロール可能なポップアップメニューを表示します。
---
category: swing
folder: BasicComboPopup
title: JComboBoxを使ってポップアップメニューをスクロール
tags: [BasicComboPopup, JTextPane, JComboBox]
author: aterai
pubdate: 2005-10-17T19:42:35+09:00
description: JComboBoxを使ってスクロール可能なポップアップメニューを表示します。
image: https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTH_tpIbsI/AAAAAAAAASE/DrHgihVbnn0/s800/BasicComboPopup.png
---
* 概要 [#summary]
`JComboBox`を使ってスクロール可能なポップアップメニューを表示します。

-&jnlp;
-&jar;
-&zip;
#download(https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTH_tpIbsI/AAAAAAAAASE/DrHgihVbnn0/s800/BasicComboPopup.png)

//#screenshot
#ref(http://lh3.ggpht.com/_9Z4BYR88imo/TQTH_tpIbsI/AAAAAAAAASE/DrHgihVbnn0/s800/BasicComboPopup.png)

**サンプルコード [#q28e6ef6]
* サンプルコード [#sourcecode]
#code(link){{
JComboBox combo = new JComboBox(strArray);
BasicComboPopup popup = new BasicComboPopup(combo) {
  @Override public boolean isFocusable() {
    return true;
class EditorComboPopup extends BasicComboPopup {
  private final JTextComponent textArea;
  private transient MouseAdapter listener;
  protected EditorComboPopup(JTextComponent textArea, JComboBox cb) {
    super(cb);
    this.textArea = textArea;
  }
  private MouseAdapter listener = null;

  @Override protected void installListListeners() {
    super.installListListeners();
    listener = new MouseAdapter() {
      @Override public void mouseClicked(MouseEvent e) {
        hide();
        System.out.println(comboBox.getSelectedItem());
        append((String)combo.getSelectedItem());
        String str = (String) comboBox.getSelectedItem();
        try {
          Document doc = textArea.getDocument();
          doc.insertString(textArea.getCaretPosition(), str, null);
        } catch (BadLocationException ex) {
          ex.printStackTrace();
        }
      }
    };
    if(listener!=null) {
    if (Objects.nonNull(list)) {
      list.addMouseListener(listener);
    }
  }

  @Override public void uninstallingUI() {
    if(listener != null) {
    if (Objects.nonNull(listener)) {
      list.removeMouseListener(listener);
      listener = null;
    }
    super.uninstallingUI();
  }
};

  @Override public boolean isFocusable() {
    return true;
  }
}
}}

**解説 [#z7e217c3]
上記のサンプルでは、KBD{Shift}+KBD{TAB}でポップアップメニューが表示され、KBD{Up}KBD{Down}キーで移動、KBD{Enter}で``JTextPane``のカーソルの後に選択された文字列が入力されます。
* 解説 [#explanation]
上記のサンプルでは、KBD{Shift+Tab}でポップアップメニューが表示され、KBD{Up}・KBD{Down}キーで移動、KBD{Enter}で`JTextPane`のカーソルの後に選択された文字列が入力されます。

コンボボックスのポップアップ部分の``UI``を表現する``BasicComboPopup``を利用することで、スクロールバーをもつポップアップメニューを実現しています。
`JComboBox`のポップアップ部分の`UI`を表現する`BasicComboPopup`を利用することで垂直スクロールバーありのポップアップメニューを実現しています。

フォースを取得して、キー入力で選択を変更できるように、``BasicComboPopup#isFocusable``メソッドをオーバーライドしています。また、``BasicComboPopup#show``したあと、``BasicComboPopup#requestFocusInWindow``する必要があります。
- フォーカスを取得してキー入力で選択を変更できるように`BasicComboPopup#isFocusable`メソッドをオーバーライド
-- `BasicComboPopup#show()`を実行した後`BasicComboPopup#requestFocusInWindow()`を呼びだす必要がある

----
``JFrame``から、ポップアップメニューがはみ出す(親``Window``が``HeavyWeightWindow``になる)場合、カーソルキーなどで、アイテムが移動選択できないバグがあったので、``SwingUtilities.getWindowAncestor(popup).toFront();``を追加するなどの修正(``Ubuntu``ではうまく動作しない?)をしました。

- %%`JFrame`から、ポップアップメニューがはみ出す(親`Window`が`HeavyWeightWindow`になる)場合、カーソルキーなどで、アイテムが移動選択できないバグがある%%
-- `SwingUtilities.getWindowAncestor(popup).toFront();`を追加して修正(`Ubuntu`ではうまく動作しない?)
#code{{
private void popupMenu(ActionEvent e) {
  Rectangle rect = getMyPopupRect();
  popup.show(jtp, rect.x, rect.y + rect.height);
  EventQueue.invokeLater(new Runnable() {
    @Override public void run() {
      SwingUtilities.getWindowAncestor(popup).toFront();
      popup.requestFocusInWindow();
    }
  });
}
}}
//#screenshot(,screenshot1.png)
#ref(http://lh3.ggpht.com/_9Z4BYR88imo/TQTICNIyr1I/AAAAAAAAASI/CorNUGA0pF8/s800/BasicComboPopup1.png)
#ref(https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTICNIyr1I/AAAAAAAAASI/CorNUGA0pF8/s800/BasicComboPopup1.png)

- %%ただし、バージョン(``6uN``?)、``Web Start``などで実行すると、``AccessControlException``が発生します。%%
- %%ただし、バージョン(`6uN`?)、`Web Start`などで実行すると、`AccessControlException`が発生する%%
-- `Exception in thread "AWT-EventQueue-0" java.security.AccessControlException: access denied (java.awt.AWTPermission setWindowAlwaysOnTop)`
- 上記の`AccessControlException`は、`6u10 build b26`で修正されている
-- [https://bugs.openjdk.org/browse/JDK-6675802 Bug ID: 6675802 Regression: heavyweight popups cause SecurityExceptions in applets]

 Exception in thread "AWT-EventQueue-0" java.security.AccessControlException: access denied (java.awt.AWTPermission setWindowAlwaysOnTop)
* 参考リンク [#reference]
- [https://community.oracle.com/thread/1367473 Swing - Scrollable PopupMenu]
- [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/plaf/basic/BasicComboPopup.html BasicComboPopup (Java Platform SE 8)]

- 上記の``AccessControlException``は、``6u10 build b26``で修正されている
-- [http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6675802 Bug ID: 6675802 Regression: heavyweight popups cause SecurityExceptions in applets]
* コメント [#comment]
#comment
- 大変参考になりました。その上、マウスクリックで文字列を選定できるようにしたいですが、どうすればいかがですか? -- &user(java); &new{2008-01-08 (火) 16:25:30};
-- どうもです。とりあえず(勘違いしているかもしれませんが、以前はマウスクリックでも動作していたような…?)、手抜きですが、`BasicComboPopup#installListListeners`メソッドをオーバーライドしてマウスリスナーを追加してみました。 -- &user(aterai); &new{2008-01-08 (火) 18:23:22};
- 助かりました!感動です!ご回答ありがとうございました。 -- &user(java); &new{2008-01-10 (木) 17:38:04};
- こんにちは。いつもこのサイトを参考にさせていただいています。ようやく自分の`java`アプリケーションをリリースしました(http://www.jdbckit.com  まだ更新中ですが、)。次回のバージョンアップで、`Special Thanks`をバージョン情報画面に設けて、Terai Atsuhiro様のサイトを感謝対象にさせてよろしいでしょうか? -- &user(java); &new{2008-02-22 (金) 15:13:04};
-- こんばんは。どうもです。おお、おめでとうございます。リンクの件はご自由にどうぞ。 -- &user(aterai); &new{2008-02-22 (金) 17:00:18};
-- 余談: ドキュメントに何か書く必要があるのって、`Apache Software License`でしたっけ?基本的(引用先を強調している`Tips`を除く)に、このサイトの`Tips`は、ちいさなサンプルを目指しているため、コピペしても単独ではあまり役に立たないものが多く、完全に無保証なので、ライセンスなどは気しなくても良いです。 -- &user(aterai); &new{2008-02-22 (金) 17:01:08};

**参考リンク [#ieff35f1]
-[http://forums.sun.com/thread.jspa?threadID=483165 Swing - Scrollable PopupMenu]

**コメント [#c9eef0fd]
- 大変参考になりました。その上、マウスクリックで文字列を選定できるようにしたいですが、どうすればいかがですか? -- [[java]] &new{2008-01-08 (火) 16:25:30};
-- どうもです。とりあえず(以前は、マウスクリックでも動作していたと思うのですが、勘違いだったのかも…?)、手抜きですが、``BasicComboPopup#installListListeners``メソッドをオーバーライドしてマウスリスナーを追加してみました。 -- [[aterai]] &new{2008-01-08 (火) 18:23:22};
- 助かりました!感動です!ご回答ありがとうございました。 -- [[java]] &new{2008-01-10 (木) 17:38:04};
- こんにちは。いつもこのサイトを参考にさせていただいています。ようやく自分の``java``アプリケーションをリリースしました(http://www.jdbckit.com  まだ更新中ですが、)。次回のバージョンアップで、``Special Thanks``をバージョン情報画面に設けて、Terai Atsuhiro様のサイトを感謝対象にさせてよろしいでしょうか? -- [[java]] &new{2008-02-22 (金) 15:13:04};
-- こんばんは。どうもです。おお、おめでとうございます。リンクの件はご自由にどうぞ。 -- [[aterai]] &new{2008-02-22 (金) 17:00:18};
-- 余談: ドキュメントに何か書く必要があるのって、``Apache Software License``でしたっけ?基本的(引用先を強調している``Tips``を除く)に、このサイトの``Tips``は、ちいさなサンプルを目指しているため、コピペしても単独ではあまり役に立たないものが多く、完全に無保証なので、ライセンスなどは気しなくても良いです。 -- [[aterai]] &new{2008-02-22 (金) 17:01:08};

#comment