JComboBox 搜索列表
JComboBox search list
我想要 JComboBox
可以搜索内容。
我试过AutoCompleteDecorator, GlazedLists, SwingLabs, JIDE, Laf-Widget
,但都无法通过第二个关键字搜索。
例如,在此代码中可以按第一个字母搜索,并且此内容仅包含一个词。
this.comboBox = new JComboBox(new Object[] { "Ester", "Jordi", "Jordina", "Jorge", "Sergi" });
AutoCompleteDecorator.decorate(this.comboBox);
如果JComboBox
内容由2或3个词组成,例如:"Ester Jordi"或"Jorge Sergi",在这种情况下如果我输入"Sergi",JComboBox
不要什么都不显示,因为它可以通过第一个词识别。
请问有什么办法可以解决这个问题吗?
我重构了给定的代码。它可以通过片段识别。所以当你输入 "English".
时,"American English" 和 "English" 会被识别
您可以在您的程序中使用 FilterComboBox class。
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();
}
}
}
在 Demo 程序中查看 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();
}
}
另一种方法,我们将现有的组合框变成过滤后的组合框。有点"decoration".
"Decorator" class.
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();
}
}
}
示范[=31=].
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();
}
}
在尝试执行的时候遇到了两个问题:
当按下键盘上的(向上、向下、输入)按钮时。我通过阻止他们使用 return
语句来解决它。
每次在文本字段中写入时都会触发 popupMenuWillBecomeInvisble()。
我通过在 popupMenuWillBecomeInvisible
内的主框架中添加 getKeyStat()
解决了这个问题
希望对您有所帮助!
private voidjCombobox1popupMenuWillBecomeInvisble(javax.swing.event.PopupMenuEvent evt){
if(JComboBoxDecorator.getKeyStat().equals("enter")){
//write yor code here
}
}
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;
/**
* Makes given combo box editable and filterable.
*/
public class JComboBoxDecorator {
static String checkenter="";
public static String getKeyStat(){
return checkenter;
}
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() {
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){
checkenter = "enter";
}
}
@Override
public void keyReleased(KeyEvent e) {
SwingUtilities.invokeLater(() -> {
if(e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode()==KeyEvent.VK_ENTER){
// e.consume();
return ;
}
else{
comboFilter(textField.getText(), jcb, entries);
}
});
checkenter = "type";
}
}
);
}
/**
* 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<>();
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();
}
}
}
我想要 JComboBox
可以搜索内容。
我试过AutoCompleteDecorator, GlazedLists, SwingLabs, JIDE, Laf-Widget
,但都无法通过第二个关键字搜索。
例如,在此代码中可以按第一个字母搜索,并且此内容仅包含一个词。
this.comboBox = new JComboBox(new Object[] { "Ester", "Jordi", "Jordina", "Jorge", "Sergi" });
AutoCompleteDecorator.decorate(this.comboBox);
如果JComboBox
内容由2或3个词组成,例如:"Ester Jordi"或"Jorge Sergi",在这种情况下如果我输入"Sergi",JComboBox
不要什么都不显示,因为它可以通过第一个词识别。
请问有什么办法可以解决这个问题吗?
我重构了给定的代码。它可以通过片段识别。所以当你输入 "English".
时,"American English" 和 "English" 会被识别您可以在您的程序中使用 FilterComboBox class。
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();
}
}
}
在 Demo 程序中查看 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();
}
}
另一种方法,我们将现有的组合框变成过滤后的组合框。有点"decoration".
"Decorator" class.
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();
}
}
}
示范[=31=].
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();
}
}
在尝试执行的时候遇到了两个问题:
当按下键盘上的(向上、向下、输入)按钮时。我通过阻止他们使用
return
语句来解决它。每次在文本字段中写入时都会触发 popupMenuWillBecomeInvisble()。 我通过在
内的主框架中添加popupMenuWillBecomeInvisible
getKeyStat()
解决了这个问题
希望对您有所帮助!
private voidjCombobox1popupMenuWillBecomeInvisble(javax.swing.event.PopupMenuEvent evt){
if(JComboBoxDecorator.getKeyStat().equals("enter")){
//write yor code here
}
}
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;
/**
* Makes given combo box editable and filterable.
*/
public class JComboBoxDecorator {
static String checkenter="";
public static String getKeyStat(){
return checkenter;
}
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() {
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){
checkenter = "enter";
}
}
@Override
public void keyReleased(KeyEvent e) {
SwingUtilities.invokeLater(() -> {
if(e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode()==KeyEvent.VK_ENTER){
// e.consume();
return ;
}
else{
comboFilter(textField.getText(), jcb, entries);
}
});
checkenter = "type";
}
}
);
}
/**
* 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<>();
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();
}
}
}