Swing/ComboBoxSuggestion のバックアップ(No.27)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/ComboBoxSuggestion へ行く。
- 1 (2009-01-22 (木) 16:26:11)
- 2 (2010-11-11 (木) 15:07:51)
- 3 (2010-11-11 (木) 16:55:21)
- 4 (2010-11-12 (金) 16:07:18)
- 5 (2011-02-20 (日) 17:03:02)
- 6 (2011-02-20 (日) 19:14:25)
- 7 (2011-02-21 (月) 15:06:15)
- 8 (2012-05-06 (日) 19:23:33)
- 9 (2013-04-14 (日) 00:39:36)
- 10 (2013-05-26 (日) 05:18:41)
- 11 (2013-07-26 (金) 01:12:13)
- 12 (2013-07-27 (土) 01:00:47)
- 13 (2014-03-18 (火) 18:51:29)
- 14 (2014-04-14 (月) 11:04:20)
- 15 (2014-04-14 (月) 17:46:28)
- 16 (2014-11-29 (土) 01:46:43)
- 17 (2015-01-28 (水) 15:08:34)
- 18 (2016-05-31 (火) 14:26:21)
- 19 (2016-09-27 (火) 17:22:04)
- 20 (2017-03-28 (火) 15:22:16)
- 21 (2018-01-31 (水) 20:29:00)
- 22 (2018-02-20 (火) 15:24:10)
- 23 (2018-02-24 (土) 19:51:30)
- 24 (2018-06-01 (金) 14:24:46)
- 25 (2018-10-25 (木) 17:42:07)
- 26 (2018-11-08 (木) 17:49:12)
- 27 (2020-11-05 (木) 11:34:48)
- 28 (2022-08-20 (土) 22:15:25)
- 29 (2022-10-20 (木) 21:25:59)
- category: swing
folder: ComboBoxSuggestion
title: JComboBoxで候補一覧を表示
tags: [JComboBox, KeyListener, JPopupMenu]
author: aterai
pubdate: 2004-12-06T09:47:32+09:00
description: JComboBoxに入力候補の一覧表示機能(補完機能、コードアシスト、コンテンツアシスト)を追加します。
image:
hreflang:
href: https://java-swing-tips.blogspot.com/2009/01/create-auto-suggest-jcombobox.html lang: en
概要
JComboBox
に入力候補の一覧表示機能(補完機能、コードアシスト、コンテンツアシスト)を追加します。
Screenshot
Advertisement
サンプルコード
String[] array = {
"aaaa", "aaaabbb", "aaaabbbcc", "aaaabbbccddd",
"abcde", "abefg", "bbb1", "bbb12"};
JComboBox combo = new JComboBox(array);
combo.setEditable(true);
combo.setSelectedIndex(-1);
JTextField field = (JTextField) combo.getEditor().getEditorComponent();
field.setText("");
field.addKeyListener(new ComboKeyHandler(combo));
View in GitHub: Java, Kotlinclass ComboKeyHandler extends KeyAdapter {
private final JComboBox<String> comboBox;
private final List<String> list = new ArrayList<>();
private boolean shouldHide;
public ComboKeyHandler(JComboBox<String> combo) {
super();
this.comboBox = combo;
for (int i = 0; i < comboBox.getModel().getSize(); i++) {
list.add(comboBox.getItemAt(i));
}
}
@Override public void keyTyped(final KeyEvent e) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
String text = ((JTextField) e.getComponent()).getText();
ComboBoxModel<String> m;
if (text.isEmpty()) {
String[] array = list.toArray(new String[list.size()]);
m = new DefaultComboBoxModel<String>(array);
setSuggestionModel(comboBox, m, "");
comboBox.hidePopup();
} else {
m = getSuggestedModel(list, text);
if (m.getSize() == 0 || shouldHide) {
comboBox.hidePopup();
} else {
setSuggestionModel(comboBox, m, text);
comboBox.showPopup();
}
}
}
});
}
@Override public void keyPressed(KeyEvent e) {
JTextField textField = (JTextField) e.getComponent();
String text = textField.getText();
shouldHide = false;
switch (e.getKeyCode()) {
case KeyEvent.VK_RIGHT:
for (String s : list) {
if (s.startsWith(text)) {
textField.setText(s);
return;
}
}
break;
case KeyEvent.VK_ENTER:
if (!list.contains(text)) {
list.add(text);
Collections.sort(list);
setSuggestionModel(comboBox, getSuggestedModel(list, text), text);
}
shouldHide = true;
break;
case KeyEvent.VK_ESCAPE:
shouldHide = true;
break;
default:
break;
}
}
private static void setSuggestionModel(
JComboBox<String> comboBox, ComboBoxModel<String> mdl, String str) {
comboBox.setModel(mdl);
comboBox.setSelectedIndex(-1);
((JTextField) comboBox.getEditor().getEditorComponent()).setText(str);
}
private static ComboBoxModel<String> getSuggestedModel(List<String> list, String text) {
DefaultComboBoxModel<String> m = new DefaultComboBoxModel<>();
for (String s : list) {
if (s.startsWith(text)) {
m.addElement(s);
}
}
return m;
}
}
解説
上記のサンプルでは、次のキー操作に対応しています。
- UpDownキー
- ポップアップ表示
- Escキー
- ポップアップ非表示
- Rightキー
- 補完
- Enterキー
- 選択、または追加
- 文字入力
- 候補をポップアップ
JComboBox#showPopup()
とJComboBox#hidePopup()
を使って、候補のポップアップメニュー表示を制御- 候補を表示するとき、
JComboBox#setSelectedIndex(-1)
で項目の選択を一旦クリアしないと動作がおかしくなる場合がある
- 候補を表示するとき、
JComboBox
ではなく、SwingSet3
のJHistoryTextField.java のように、JTextField
+JPopupMenu
を使用することもできますが、画面の下側で候補数が変更された場合のJPopupMenu
の位置更新(気にしなければ問題無し)が面倒です。JTextField
風に見せかけたいだけなら、以下のようなArrowButton
を非表示にする方法もあります。
//UIManager.put("ComboBox.squareButton", Boolean.FALSE);
JComboBox = new JComboBox(model) {
@Override public void updateUI() {
super.updateUI();
setUI(new javax.swing.plaf.basic.BasicComboBoxUI() {
@Override protected JButton createArrowButton() {
JButton button = new JButton() {
@Override public int getWidth() {
return 0;
}
};
button.setBorder(BorderFactory.createEmptyBorder());
button.setVisible(false);
return button;
}
@Override public void configureArrowButton() {}
});
for (MouseListener ml: getMouseListeners()) {
removeMouseListener(ml);
}
}
};