JComboBoxを使ってポップアップメニューをスクロール
Total: 15251
, Today: 2
, Yesterday: 0
Posted by aterai at
Last-modified:
概要
JComboBox
を使ってスクロール可能なポップアップメニューを表示します。
Screenshot
Advertisement
サンプルコード
class EditorComboPopup extends BasicComboPopup {
private final JTextComponent textArea;
private transient MouseAdapter listener;
protected EditorComboPopup(JTextComponent textArea, JComboBox cb) {
super(cb);
this.textArea = textArea;
}
@Override protected void installListListeners() {
super.installListListeners();
listener = new MouseAdapter() {
@Override public void mouseClicked(MouseEvent e) {
hide();
String str = (String) comboBox.getSelectedItem();
try {
Document doc = textArea.getDocument();
doc.insertString(textArea.getCaretPosition(), str, null);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
};
if (Objects.nonNull(list)) {
list.addMouseListener(listener);
}
}
@Override public void uninstallingUI() {
if (Objects.nonNull(listener)) {
list.removeMouseListener(listener);
listener = null;
}
super.uninstallingUI();
}
@Override public boolean isFocusable() {
return true;
}
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、Shift+Tabでポップアップメニューが表示され、Up・Downキーで移動、EnterでJTextPane
のカーソルの後に選択された文字列が入力されます。
JComboBox
のポップアップ部分のUI
を表現するBasicComboPopup
を利用することで垂直スクロールバーありのポップアップメニューを実現しています。
- フォーカスを取得してキー入力で選択を変更できるように
BasicComboPopup#isFocusable
メソッドをオーバーライドBasicComboPopup#show()
を実行した後BasicComboPopup#requestFocusInWindow()
を呼びだす必要がある
JFrame
から、ポップアップメニューがはみ出す(親Window
がHeavyWeightWindow
になる)場合、カーソルキーなどで、アイテムが移動選択できないバグがあるSwingUtilities.getWindowAncestor(popup).toFront();
を追加して修正(Ubuntu
ではうまく動作しない?)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(); } }); }
ただし、バージョン(6uN
?)、Web Start
などで実行すると、AccessControlException
が発生するException in thread "AWT-EventQueue-0" java.security.AccessControlException: access denied (java.awt.AWTPermission setWindowAlwaysOnTop)
- 上記の
AccessControlException
は、6u10 build b26
で修正されている