Swing/ComboBoxSuggestion のバックアップ(No.16)
- バックアップ一覧
 - 差分 を表示
 - 現在との差分 を表示
 - 現在との差分 - 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)
 - 30 (2025-01-03 (金) 08:57:02)
 - 31 (2025-01-03 (金) 09:01:23)
 - 32 (2025-01-03 (金) 09:02:38)
 - 33 (2025-01-03 (金) 09:03:21)
 - 34 (2025-01-03 (金) 09:04:02)
 - 35 (2025-06-19 (木) 12:41:37)
 - 36 (2025-06-19 (木) 12:43:47)
 
 
- title: JComboBoxで候補一覧を表示 tags: [JComboBox, KeyListener, JPopupMenu] author: aterai pubdate: 2004-12-06 description: JComboBoxに入力候補の一覧表示機能(補完機能、コードアシスト、コンテンツアシスト)を追加します。
 
概要
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((String) 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, new DefaultComboBoxModel(list), text);
        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#setPopupVisibleメソッドをラップしているだけ)を使って、候補のポップアップメニュー表示を制御します。
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);
    }
  }
};