java中的jcomboboxfilter – 外观独立

我有一个简单的JComboBoxfilter代码,如下所示:

import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.List; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.UIManager; public class FilterComboBox extends JComboBox { private List array; public FilterComboBox(List array) { super(array.toArray()); this.array = array; this.setEditable(true); final JTextField textfield = (JTextField) this.getEditor().getEditorComponent(); textfield.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent ke) { SwingUtilities.invokeLater(new Runnable() { public void run() { comboFilter(textfield.getText()); } }); } }); } public void comboFilter(String enteredText) { List filterArray= new ArrayList(); for (int i = 0; i  0) { this.setModel(new DefaultComboBoxModel(filterArray.toArray())); this.setSelectedItem(enteredText); this.showPopup(); } else { this.hidePopup(); } } /* Testing Codes */ public static List populateArray() { List test = new ArrayList(); test.add(""); test.add("Mountain Flight"); test.add("Mount Climbing"); test.add("Trekking"); test.add("Rafting"); test.add("Jungle Safari"); test.add("Bungie Jumping"); test.add("Para Gliding"); return test; } public static void makeUI() { JFrame frame = new JFrame("Adventure in Nepal - Combo Filter Test"); FilterComboBox acb = new FilterComboBox(populateArray()); frame.getContentPane().add(acb); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } public static void main(String[] args) throws Exception { //UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); makeUI(); } } 

组合filter的性能不是很好,但对于少数数据集来说它很好。 我的问题是 – 当我删除评论UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); 要改变外观,filter不起作用。 在WindowsLookAndFeel中,combobox仅通过替换先前输入的字符来获取单个字符。

键入'moun'后输出不同

你能告诉我发生什么事吗? Manoj Shrestha的答案在某种程度上有所帮助,但是,您能否提供一些其他建议来实现Java中的comboboxfilter?

首先,您每次都在创建新模型,然后从代码调用show popup导致闪烁等。我们可以修改模型本身。 其次,您将当前输入的文本设置为所选项目,似乎具有其他人所指出的selectAll行为。 我修改了代码如下:

 public void comboFilter(String enteredText) { if (!this.isPopupVisible()) { this.showPopup(); } List filterArray= new ArrayList(); for (int i = 0; i < array.size(); i++) { if (array.get(i).toLowerCase().contains(enteredText.toLowerCase())) { filterArray.add(array.get(i)); } } if (filterArray.size() > 0) { DefaultComboBoxModel model = (DefaultComboBoxModel) this.getModel(); model.removeAllElements(); for (String s: filterArray) model.addElement(s); JTextField textfield = (JTextField) this.getEditor().getEditorComponent(); textfield.setText(enteredText); } } 

希望对你有效。

很长的答案,我认为关于不同的外观和感觉如何在API中实现方法并且有效的例子

  • KeyListener不是适合Swing JComponents的监听器,你真的要打扰KeyBindings,

  • KeyListener是简单的异步,

  • JComboBox是复合JComponent,然后需要覆盖内部JComponents,KeyListener的所有输出都必须包装到invokeLater()中,注意我可以从coumpond JComponents创建事件,两次invokeLater()不会将预期输出返回给GUI,只有Swing具有Swing Action的计时器可以正确地做到这一点,简单的为什么要打扰那个关于错误方式的例子,

 import java.awt.Component; import java.awt.event.*; import javax.swing.*; import javax.swing.plaf.basic.BasicComboBoxRenderer; public class ComboBoxHoverOver { private JComboBox combo = new JComboBox(); public ComboBoxHoverOver() { combo.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXX"); combo.setRenderer(new ComboToolTipRenderer(combo)); combo.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { //System.out.println(combo.getSelectedItem().toString()); } }); combo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { //System.out.println(combo.getSelectedItem().toString()); } }); combo.addItem(""); combo.addItem("Long text 4"); combo.addItem("Long text 3"); combo.addItem("Long text 2"); combo.addItem("Long text 1"); JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(combo); f.pack(); f.setVisible(true); } private class ComboToolTipRenderer extends BasicComboBoxRenderer { private static final long serialVersionUID = 1L; private JComboBox combo; private JList comboList; ComboToolTipRenderer(JComboBox combo) { this.combo = combo; } @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus); if (comboList == null) { comboList = list; KeyAdapter listener = new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_UP) { int x = 5; int y = comboList.indexToLocation(comboList.getSelectedIndex()).y; System.out.println(comboList.getSelectedIndex()); } } }; combo.addKeyListener(listener); combo.getEditor().getEditorComponent().addKeyListener(listener); } if (isSelected) { //System.out.println(value.toString()); } return this; } } public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); java.awt.EventQueue.invokeLater(new Runnable() { @Override public void run() { ComboBoxHoverOver comboBoxHoverOver = new ComboBoxHoverOver(); } }); } } 
  • JComboBox是复合JComponent,然后需要覆盖BasicComboBoxUI,请抱歉我懒得编写和模拟太长的代码作为第一点的代码

  • 否则所有来自上述两点的努力都是无用的和反作用的,没有别的,只有DOT


请有人测试* nix和apple OS X中的代码

来自我的Java6 WinXP组件(所有重要的内容都隐藏在使用过的方法中,对来自前Sun Microsystems的匿名作者感到荣幸)

物质L&F

在此处输入图像描述

WindowsLookAndFeel L&F

在此处输入图像描述

Nimbus L&F

在此处输入图像描述

金属L&F

在此处输入图像描述

来自Java Classes

主要

 import java.awt.*; import java.util.ArrayList; import javax.swing.*; import javax.swing.UIManager.LookAndFeelInfo; import org.pushingpixels.substance.api.skin.SubstanceOfficeSilver2007LookAndFeel; public class AutoCompleteTextField { private static JFrame frame = new JFrame(); private ArrayList listSomeString = new ArrayList(); private Java2sAutoTextField someTextField = new Java2sAutoTextField(listSomeString); private ArrayList listSomeAnotherString = new ArrayList(); private Java2sAutoComboBox someComboBox = new Java2sAutoComboBox(listSomeAnotherString); public AutoCompleteTextField() { listSomeString.add("-"); listSomeString.add("Snowboarding"); listSomeString.add("Rowing"); listSomeString.add("Knitting"); listSomeString.add("Speed reading"); listSomeString.add("Pool"); listSomeString.add("None of the above"); // listSomeAnotherString.add("-"); listSomeAnotherString.add("XxxZxx Snowboarding"); listSomeAnotherString.add("AaaBbb Rowing"); listSomeAnotherString.add("CccDdd Knitting"); listSomeAnotherString.add("Eee Fff Speed reading"); listSomeAnotherString.add("Eee Fff Pool"); listSomeAnotherString.add("Eee Fff None of the above"); // someTextField.setFont(new Font("Serif", Font.BOLD, 16)); someTextField.setForeground(Color.black); someTextField.setBackground(Color.orange); someTextField.setName("someTextField"); someTextField.setDataList(listSomeString); // someComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); someComboBox.setFont(new Font("Serif", Font.BOLD, 16)); someComboBox.setForeground(Color.black); someComboBox.setBackground(Color.YELLOW); someComboBox.getEditor().selectAll(); someComboBox.getEditor().getEditorComponent().setBackground(Color.YELLOW); ((JTextField) someComboBox.getEditor().getEditorComponent()).setDisabledTextColor(Color.black); someComboBox.setName("someComboBox"); someComboBox.setDataList(listSomeAnotherString); // frame.setLayout(new GridLayout(0, 1, 10, 10)); frame.add(someTextField); frame.add(someComboBox); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocation(100, 100); frame.pack(); frame.setVisible(true); // SwingUtilities.invokeLater(new Runnable() { @Override public void run() { someTextField.setText("-"); someComboBox.getEditor().setItem(0); someComboBox.getEditor().selectAll(); someTextField.grabFocus(); someTextField.requestFocus(); someTextField.setText(someTextField.getText()); someTextField.selectAll(); } }); } public static void main(String[] args) { /*SwingUtilities.invokeLater(new Runnable() { public void run() { try { UIManager.setLookAndFeel(new SubstanceOfficeSilver2007LookAndFeel()); SwingUtilities.updateComponentTreeUI(frame); } catch (UnsupportedLookAndFeelException e) { throw new RuntimeException(e); } } });*/ /*try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { System.out.println(info.getName()); if ("Nimbus".equals(info.getName())) { UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (UnsupportedLookAndFeelException e) { // handle exception } catch (ClassNotFoundException e) { // handle exception } catch (InstantiationException e) { // handle exception } catch (IllegalAccessException e) { // handle exception }*/ SwingUtilities.invokeLater(new Runnable() { @Override public void run() { AutoCompleteTextField aCTF = new AutoCompleteTextField(); } }); } } 

AutoComboBox

 import java.awt.event.ItemEvent; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.plaf.basic.BasicComboBoxEditor; public class Java2sAutoComboBox extends JComboBox { private static final long serialVersionUID = 1L; private AutoTextFieldEditor autoTextFieldEditor; private boolean isFired; private class AutoTextFieldEditor extends BasicComboBoxEditor { private Java2sAutoTextField getAutoTextFieldEditor() { return (Java2sAutoTextField) editor; } AutoTextFieldEditor(java.util.List list) { editor = new Java2sAutoTextField(list, Java2sAutoComboBox.this); } } public Java2sAutoComboBox(java.util.List list) { isFired = false; autoTextFieldEditor = new AutoTextFieldEditor(list); setEditable(true); setModel(new DefaultComboBoxModel(list.toArray()) { private static final long serialVersionUID = 1L; @Override protected void fireContentsChanged(Object obj, int i, int j) { if (!isFired) { super.fireContentsChanged(obj, i, j); } } }); setEditor(autoTextFieldEditor); } public boolean isCaseSensitive() { return autoTextFieldEditor.getAutoTextFieldEditor().isCaseSensitive(); } public void setCaseSensitive(boolean flag) { autoTextFieldEditor.getAutoTextFieldEditor().setCaseSensitive(flag); } public boolean isStrict() { return autoTextFieldEditor.getAutoTextFieldEditor().isStrict(); } public void setStrict(boolean flag) { autoTextFieldEditor.getAutoTextFieldEditor().setStrict(flag); } public java.util.List getDataList() { return autoTextFieldEditor.getAutoTextFieldEditor().getDataList(); } public void setDataList(java.util.List list) { autoTextFieldEditor.getAutoTextFieldEditor().setDataList(list); setModel(new DefaultComboBoxModel(list.toArray())); } void setSelectedValue(Object obj) { if (isFired) { return; } else { isFired = true; setSelectedItem(obj); fireItemStateChanged(new ItemEvent(this, 701, selectedItemReminder, 1)); isFired = false; return; } } @Override protected void fireActionEvent() { if (!isFired) { super.fireActionEvent(); } } } 

AutoTextField

 import java.util.List; import javax.swing.JTextField; import javax.swing.text.*; public class Java2sAutoTextField extends JTextField { private static final long serialVersionUID = 1L; private List dataList; private boolean isCaseSensitive; private boolean isStrict; private Java2sAutoComboBox autoComboBox; public class AutoDocument extends PlainDocument { private static final long serialVersionUID = 1L; @Override public void replace(int i, int j, String s, AttributeSet attributeset) throws BadLocationException { super.remove(i, j); insertString(i, s, attributeset); } @Override public void insertString(int i, String s, AttributeSet attributeset) throws BadLocationException { if (s == null || "".equals(s)) { return; } String s1 = getText(0, i); String s2 = getMatch(s1 + s); int j = (i + s.length()) - 1; if (isStrict && s2 == null) { s2 = getMatch(s1); j--; } else if (!isStrict && s2 == null) { super.insertString(i, s, attributeset); return; } if (autoComboBox != null && s2 != null) { autoComboBox.setSelectedValue(s2); } super.remove(0, getLength()); super.insertString(0, s2, attributeset); setSelectionStart(j + 1); setSelectionEnd(getLength()); } @Override public void remove(int i, int j) throws BadLocationException { int k = getSelectionStart(); if (k > 0) { k--; } String s = getMatch(getText(0, k)); if (!isStrict && s == null) { super.remove(i, j); } else { super.remove(0, getLength()); super.insertString(0, s, null); } if (autoComboBox != null && s != null) { autoComboBox.setSelectedValue(s); } try { setSelectionStart(k); setSelectionEnd(getLength()); } catch (Exception exception) { } } } public Java2sAutoTextField(List list) { isCaseSensitive = false; isStrict = true; autoComboBox = null; if (list == null) { throw new IllegalArgumentException("values can not be null"); } else { dataList = list; init(); return; } } Java2sAutoTextField(List list, Java2sAutoComboBox b) { isCaseSensitive = false; isStrict = true; autoComboBox = null; if (list == null) { throw new IllegalArgumentException("values can not be null"); } else { dataList = list; autoComboBox = b; init(); return; } } private void init() { setDocument(new AutoDocument()); if (isStrict && dataList.size() > 0) { setText(dataList.get(0).toString()); } } private String getMatch(String s) { for (int i = 0; i < dataList.size(); i++) { String s1 = dataList.get(i).toString(); if (s1 != null) { if (!isCaseSensitive && s1.toLowerCase().startsWith(s.toLowerCase())) { return s1; } if (isCaseSensitive && s1.startsWith(s)) { return s1; } } } return null; } @Override public void replaceSelection(String s) { AutoDocument _lb = (AutoDocument) getDocument(); if (_lb != null) { try { int i = Math.min(getCaret().getDot(), getCaret().getMark()); int j = Math.max(getCaret().getDot(), getCaret().getMark()); _lb.replace(i, j - i, s, null); } catch (Exception exception) { } } } public boolean isCaseSensitive() { return isCaseSensitive; } public void setCaseSensitive(boolean flag) { isCaseSensitive = flag; } public boolean isStrict() { return isStrict; } public void setStrict(boolean flag) { isStrict = flag; } public List getDataList() { return dataList; } public void setDataList(List list) { if (list == null) { throw new IllegalArgumentException("values can not be null"); } else { dataList = list; return; } } } 

编辑

Win7 64b / Java7的输出

金属L&F

在此处输入图像描述

Windows L&F(JComboBox中Button附近有趣的空白空间)

在此处输入图像描述

Nimbus L&F

在此处输入图像描述

随时可以编辑

该组件称为自动完成,并包含在所谓的swing扩展项中。

请看一下: http : //swingx.java.net/
有一个webstart: http : //swinglabs-demos.java.net/demos/swingxset6/swingxset.jnlp

自动填充是要选择的菜单。 玩得开心,不易出错的代码:)

很明显,故障是在使用的文本域组件中。 所发生的情况是,当使用Windows外观时,使用“textfield.selectAll();”行选择此组件中的文本,因此当您键入任何其他内容时,将从textfield组件中清除所选文本。 因此,在下面的代码中,调整了该组件的插入位置。 这是它的工作原理,首先将文本字段的当前插入位置存储在变量“currentCaretPosition”中,然后将插入符号位置移动到组件中文本的开头。 过滤后将插入位置恢复为“currentCaretPosition”变量值。 我希望它能按你的意愿运作。

精炼代码如下: –

  /****Beginning of code****/ import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.List; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.UIManager; public class FilterComboBox extends JComboBox { private List array; private int currentCaretPosition=0; public FilterComboBox(List array) { super(array.toArray()); this.array = array; this.setEditable(true); final JTextField textfield = (JTextField) this.getEditor().getEditorComponent(); textfield.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent ke) { SwingUtilities.invokeLater(new Runnable() { public void run() { currentCaretPosition=textfield.getCaretPosition(); if(textfield.getSelectedText()==null) { textfield.setCaretPosition(0); comboFilter(textfield.getText()); textfield.setCaretPosition(currentCaretPosition); } } }); } }); } public void comboFilter(String enteredText) { List filterArray= new ArrayList(); for (int i = 0; i < array.size(); i++) { if (array.get(i).toLowerCase().contains(enteredText.toLowerCase())) { filterArray.add(array.get(i)); } } if (filterArray.size() > 0) { this.setModel(new DefaultComboBoxModel(filterArray.toArray())); this.setSelectedItem(enteredText); this.showPopup(); } else { this.hidePopup(); } } /* Testing Codes */ public static List populateArray() { List test = new ArrayList(); test.add(""); test.add("Mountain Flight"); test.add("Mount Climbing"); test.add("Trekking"); test.add("Rafting"); test.add("Jungle Safari"); test.add("Bungie Jumping"); test.add("Para Gliding"); return test; } public static void makeUI() { JFrame frame = new JFrame("Adventure in Nepal - Combo Filter Test"); FilterComboBox acb = new FilterComboBox(populateArray()); frame.getContentPane().add(acb); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } public static void main(String[] args) throws Exception { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); makeUI(); } } /******* End of code**********/ 

如您所述,当用户在combobox中输入任何文本时,Windows外观会选择(突出显示)输入的文本。 因此,当您按另一个键时,它将替换前一个键。 因此,解决方案不是突出显示输入的文本。 您可以通过在keylistener中添加以下任何一个语句来实现此目的。

 textfield.setCaretPosition(textfield.getText().length()); 

要么

 textfield.setSelectionStart(textfield.getText().length()); 

所以,你的keylistener应该是这样的:

 final JTextField textfield = (JTextField) this.getEditor().getEditorComponent(); textfield.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent ke) { SwingUtilities.invokeLater(new Runnable() { public void run() { comboFilter(textfield.getText()); textfield.setCaretPosition(textfield.getText().length()); } }); } });