我重构了给定的代码。它可以通过片段识别。所以“美式英语”和“英语”在输入“English”时都会被识别出来。
您可以在程序中使用 FilterComboBox 类。
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.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
/**
* A class for filtered combo box.
*/
public class FilterComboBox
extends JComboBox
{
/**
* Entries to the combobox list.
*/
private List<String> entries;
public List<String> getEntries()
{
return entries;
}
public FilterComboBox(List<String> entries)
{
super(entries.toArray());
this.entries = entries ;
this.setEditable(true);
final JTextField textfield =
(JTextField) this.getEditor().getEditorComponent();
/**
* Listen for key presses.
*/
textfield.addKeyListener(new KeyAdapter()
{
public void keyReleased(KeyEvent ke)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
/**
* On key press filter the list.
* If there is "text" entered in text field of this combo use that "text" for filtering.
*/
comboFilter(textfield.getText());
}
});
}
});
}
/**
* Build a list of entries that match the given filter.
*/
public void comboFilter(String enteredText)
{
List<String> entriesFiltered = new ArrayList<String>();
for (String entry : getEntries())
{
if (entry.toLowerCase().contains(enteredText.toLowerCase()))
{
entriesFiltered.add(entry);
}
}
if (entriesFiltered.size() > 0)
{
this.setModel(
new DefaultComboBoxModel(
entriesFiltered.toArray()));
this.setSelectedItem(enteredText);
this.showPopup();
}
else
{
this.hidePopup();
}
}
}
在演示程序中查看 FilterComboBox 的工作原理。
import javax.swing.JFrame;
import java.util.Arrays;
public class Demo
{
public static void makeUI()
{
JFrame frame = new JFrame("Your frame");
/**
* Put data to your filtered combobox.
*/
FilterComboBox fcb = new FilterComboBox(
Arrays.asList(
"",
"English",
"French",
"Spanish",
"Japanese",
"Chinese",
"American English",
"Canada French"
));
/**
* Set up the frame.
*/
frame.getContentPane().add(fcb);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) throws Exception
{
makeUI();
}
}
另一种方法,我们将现有的组合框变成过滤的组合框。这有点“装饰”。
“装饰器”类。
import java.util.List;
import java.util.ArrayList;
import javax.swing.JComboBox;
import javax.swing.JTextField;
import javax.swing.DefaultComboBoxModel;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
/**
* Makes given combobox editable and filterable.
*/
public class JComboBoxDecorator
{
public static void decorate(final JComboBox jcb, boolean editable)
{
List<String> entries = new ArrayList<>();
for (int i = 0; i < jcb.getItemCount(); i++)
{
entries.add((String)jcb.getItemAt(i));
}
decorate(jcb, editable, entries);
}
public static void decorate(final JComboBox jcb, boolean editable, final List<String> entries)
{
jcb.setEditable(editable);
jcb.setModel(
new DefaultComboBoxModel(
entries.toArray()));
final JTextField textField = (JTextField) jcb.getEditor().getEditorComponent();
textField.addKeyListener(
new KeyAdapter()
{
public void keyReleased(KeyEvent e)
{
SwingUtilities.invokeLater(
new Runnable()
{
public void run()
{
comboFilter(textField.getText(), jcb, entries);
}
}
);
}
}
);
}
/**
* Build a list of entries that match the given filter.
*/
private static void comboFilter(String enteredText, JComboBox jcb, List<String> entries)
{
List<String> entriesFiltered = new ArrayList<String>();
for (String entry : entries)
{
if (entry.toLowerCase().contains(enteredText.toLowerCase()))
{
entriesFiltered.add(entry);
}
}
if (entriesFiltered.size() > 0)
{
jcb.setModel(
new DefaultComboBoxModel(
entriesFiltered.toArray()));
jcb.setSelectedItem(enteredText);
jcb.showPopup();
}
else
{
jcb.hidePopup();
}
}
}
示范课。
import javax.swing.JFrame;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import javax.swing.JComboBox;
import javax.swing.JPanel;
public class Demo
{
public static void makeUI()
{
JFrame frame = new JFrame("Demonstration");
/**
* List of values for comboboxes.
*/
List<String> list = Arrays.asList(
"",
"English",
"French",
"Spanish",
"Japanese",
"Chinese",
"American English",
"Canada French"
);
List<String> list2 = Arrays.asList(
"",
"Anglais",
"Francais",
"Espagnol",
"Japonais",
"Chinois",
"Anglais americain",
"Canada francais"
);
/**
* Set up the frame.
*/
JPanel panel = new JPanel();
frame.add(panel);
/**
* Create ordinary comboboxes.
* These comboboxes represent premade combobox'es. Later in the run-time we make some of them filtered.
*/
JComboBox<String> jcb1 = new JComboBox<>(list.toArray(new String[0]));
panel.add(jcb1);
JComboBox<String> jcb2 = new JComboBox<>();
panel.add(jcb2);
JComboBox<String> jcb3 = new JComboBox<>(list2.toArray(new String[0]));
panel.add(jcb3);
/**
* On the run-time we convert second and third combobox'es to filtered combobox'es.
* The jcb1 combobox is left as it was.
* For the first decorated combobox supply our entries.
* For the other put entries from list2.
*/
JComboBoxDecorator.decorate(jcb2, true, list);
JComboBoxDecorator.decorate(jcb3, true);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) throws Exception
{
makeUI();
}
}