Swing/ComboBoxSuggestion のバックアップの現在との差分(No.1)
- バックアップ一覧
- 差分 を表示
- 現在との差分 - 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)
- 追加された行はこの色です。
- 削除された行はこの色です。
TITLE:JComboBoxで候補一覧を表示 #navi(../) RIGHT:Posted by [[terai]] at 2004-12-06 *JComboBoxで候補一覧を表示 [#jc5d9269] JComboBoxに入力候補の一覧表示機能((補完機能、コードアシスト、コンテンツアシスト))を追加します。 --- category: swing folder: ComboBoxSuggestion title: JComboBoxで候補一覧を表示 tags: [JComboBox, KeyListener, JPopupMenu] author: aterai pubdate: 2004-12-06T09:47:32+09:00 description: JComboBoxに入力候補の一覧表示機能(補完機能、コードアシスト、コンテンツアシスト)を追加します。 image: https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTJwW_1EoI/AAAAAAAAAU4/ENqthfUJCsc/s800/ComboBoxSuggestion.png hreflang: href: https://java-swing-tips.blogspot.com/2009/01/create-auto-suggest-jcombobox.html lang: en --- * 概要 [#summary] `JComboBox`に入力候補の一覧表示機能(補完機能、コードアシスト、コンテンツアシスト)を追加します。 -&jnlp; -&jar; -&zip; #download(https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTJwW_1EoI/AAAAAAAAAU4/ENqthfUJCsc/s800/ComboBoxSuggestion.png) #screenshot * サンプルコード [#sourcecode] #code(link){{ 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)); **サンプルコード [#c1c19fbc] #code{{ combo.setEditable(true); field = (JTextField) combo.getEditor().getEditorComponent(); field.addKeyListener(new KeyAdapter() { @Override public void keyTyped(KeyEvent e) { keyTypedInCombo(e); // ... class 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 keyPressed(KeyEvent e) { keyPressedInCombo(e); @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(); } } } }); } //public void keyReleased(KeyEvent e) { }); }} #code{{ private boolean hide_flag = false; private void keyPressedInCombo(KeyEvent ke) { String text = field.getText(); int code = ke.getKeyCode(); if(code==KeyEvent.VK_ENTER) { if(!model.contains(text)) { model.addElement(text); Collections.sort(model); setModel(getSuggestedModel(model, text), text); } hide_flag = true; //combo.hidePopup(); }else if(code==KeyEvent.VK_ESCAPE) { hide_flag = true; //combo.hidePopup(); }else if(code==KeyEvent.VK_RIGHT) { for(int i=0;i<model.size();i++) { String str = model.elementAt(i); if(str.startsWith(text)) { combo.setSelectedIndex(-1); field.setText(str); return; @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 void keyTypedInCombo(final KeyEvent ke) { EventQueue.invokeLater(new Runnable() { public void run() { String text = field.getText(); if(text.length()==0) { combo.hidePopup(); setModel(new DefaultComboBoxModel(model), ""); }else{ DefaultComboBoxModel m = getSuggestedModel(model, text); if(m.getSize()==0 || hide_flag) { combo.hidePopup(); hide_flag = false; }else{ setModel(m, text); combo.showPopup(); } 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; } } }} **解説 [#se4084d9] * 解説 [#explanation] 上記のサンプルでは、次のキー操作に対応しています。 -上下キー --ポップアップ表示 -ESCキー --ポップアップ非表示 -右キー --補完 -リターンキー --選択or追加 -文字入力 --候補をポップアップ JComboBox#showPopup()とJComboBox#hidePopup()((それぞれ、JComboBox#setPopupVisible メソッドをラップしているだけ))を使って、候補のポップアップメニュー表示を制御します。 - KBD{Up}, KBD{Down}キー -- ポップアップ表示 - KBD{Esc}キー -- ポップアップ非表示 - KBD{Right}キー -- 補完 - KBD{Enter}キー -- 選択、または追加 - 文字入力 -- 候補をポップアップ JComboBox#setSelectedIndex(-1)で、項目の選択をクリアしないと動作がおかしくなる場合があります。 ---- - `JComboBox#showPopup()`と`JComboBox#hidePopup()`を使って候補のポップアップメニュー表示を制御 -- 候補を表示するとき`JComboBox#setSelectedIndex(-1)`で項目の選択を一旦クリアしないと動作がおかしくなる場合がある //**参考リンク **コメント [#k1139ae6] - 変換途中の日本語も、問題がないともっといいですね。 -- [[toshi]] &new{2006-04-24 (月) 13:45:06}; - あー、日本語のこと全然考えてなかったです…。 -- [[terai]] &new{2006-04-24 (月) 15:54:00}; - タイトルなどを変更するとしたら AutoCompletion に? -- [[terai]] &new{2007-05-09 (水) 20:14:40}; - 日本語を考えるとKeyReleasedよりKeyTypedのほうがよさそうです -- [[foggi]] &new{2008-05-06 (火) 17:15:39}; -- ご指摘ありがとうございます。keyTyped に変更してみました((ついでにスクリーンショットなども更新))。 -- [[terai]] &new{2008-05-07 (水) 12:23:19}; ---- - `JComboBox`ではなく`SwingSet3`の[http://java.net/projects/swingset3/sources/svn/content/trunk/SwingSet3/src/com/sun/swingset3/demos/textfield/JHistoryTextField.java JHistoryTextField.java] のように`JTextField`+`JPopupMenu`を使用することも可能だが、画面の下側で候補数が変更された場合の`JPopupMenu`の位置更新が面倒 - 以下のように`ArrowButton`を非表示にして`JTextField`風に見せかける方法もある #code{{ // 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); } } }; }} * 参考リンク [#reference] - [https://bugs.openjdk.org/browse/JDK-8141502 JDK-8141502 SwingSet3 demo links are broken - Java Bug System] * コメント [#comment] #comment - 変換途中の日本語も、問題がないともっといいですね。 -- &user(toshi); &new{2006-04-24 (月) 13:45:06}; -- あー、日本語のこと全然考えてなかったです…。 -- &user(aterai); &new{2006-04-24 (月) 15:54:00}; - タイトルなどを変更するとしたら`AutoCompletion`に? -- &user(aterai); &new{2007-05-09 (水) 20:14:40}; - 日本語を考えると`KeyReleased`より`KeyTyped`のほうがよさそうです -- &user(foggi); &new{2008-05-06 (火) 17:15:39}; -- ご指摘ありがとうございます。`keyTyped`に変更してみました(ついでにスクリーンショットなども更新)。 -- &user(aterai); &new{2008-05-07 (水) 12:23:19}; - KBD{Enter}キーでの追加が無効になるバグを修正しました。 -- &user(aterai); &new{2009-01-22 (木) 16:26:11}; - 下下と入力したとき、下上と入力したときの動きがおかしいです。 -- &user(magi); &new{2011-02-19 (Sat) 22:03:02}; -- 自分の環境では再現できてません。カーソルキーを、「下、下、下、上」と入力するのでしょうか? -- &user(aterai); &new{2011-02-21 (月) 15:06:15}; - このページで`Vector`で宣言されているところが`view plain`で表示されるコードだと`List`で宣言されてますね -- &new{2014-04-14 (月) 11:04:20}; -- こんばんは。ご指摘ありがとうございます。ソースコードは可能な限り`Vector`を使用しないようにまとめて変更したのですが、`wiki`を修正するのは面倒なので結構残っているかもしれません。%%気がつけば徐々に置き換えていく予定です。:-)%% たぶん完了。 -- &user(aterai); &new{2014-04-14 (月) 17:51:02}; #comment