对于包含一些以重复字母开头的元素的JComboBox,键入两次字符将返回键入的字符,然后是其类型的第一个字符。例如,在包含ba,bb和bc的列表中键入“ bb”将返回ba。但是,如果此列表还包含bbd,则继续按“ d”将返回bbd选项。这与数字相同:键入“ 33”将返回30,而键入“ 334”将返回334。
是否可以解决此问题,以便double keyPress真正返回键入的内容?
快速示例程序:
String[] range = new String[401];
for (int i = 0; i <= 400; i++) {
range[i] = "" + i;
}
private javax.swing.JComboBox<String> jComboBox1;
jComboBox1 = new javax.swing.JComboBox<>();
getContentPane().setLayout(new java.awt.GridLayout());
jComboBox1.setModel(new javax.swing.DefaultComboBoxModel<>(range));
getContentPane().add(jComboBox1);
pack();
答案 0 :(得分:3)
通过键盘选择项目由JComboBox.KeySelectionManager
控制,令人惊讶的是,您实际上可以实现和更改
默认实现的一件事是,它将尝试根据项的第一个字符(通过String
转换为toString
)找到与按键匹配的项。与此相关的“整洁”事情是,它将从当前选定的项目(如果不是null
)中进行搜索,如果找不到其他匹配的项目,它将从模型的开头开始。>
这意味着,如果您反复键入3
,它将逐步遍历以3
开头的所有项目。 ({30
,31
,32
... 39
,300
...)
Buuuut,这显然不是您想要的,因此,您将不得不提供自己的算法。
一个非常重要的考虑因素是,当用户停止键入时会发生什么?如果用户键入了33
,然后停止,然后再次键入3
,应该怎么办?应该选择3
还是333
?
以下是一个非常基本的示例,基于默认情况下DefaultKeySelectionManager
使用的JComoBox
。它使用StringBuilder
来跟踪击键,并使用Swing Timer
提供250
毫秒的超时,它将在StringBuilder
毫秒后清除250
不活动状态(您可以将此值传递给构造函数以定义自己的值)
由JComboBox
调用时,它将简单地在模型中线性搜索其toString
结果以键入的内容开头的项目。
此示例不区分大小写,但您可以对其进行修改以满足您的特定需求
public class MyKeySelectionManager implements KeySelectionManager {
private Timer timeout;
private StringBuilder pattern = new StringBuilder(32);
public MyKeySelectionManager() {
timeout = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
pattern.delete(0, pattern.length());
}
});
timeout.setRepeats(false);
}
@Override
public int selectionForKey(char aKey, ComboBoxModel<?> model) {
timeout.stop();
pattern.append(Character.toLowerCase(aKey));
String match = pattern.toString();
for (int index = 0; index < model.getSize(); index++) {
String text = model.getElementAt(index).toString().toLowerCase();
if (text.startsWith(match)) {
timeout.start();
return index;
}
}
timeout.start();
return -1;
}
}
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComboBox.KeySelectionManager;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
for (int index = 0; index < 50; index++) {
model.addElement(Integer.toString(index));
}
JComboBox cb = new JComboBox(model);
cb.setKeySelectionManager(new MyKeySelectionManager());
JFrame frame = new JFrame();
JPanel content = new JPanel(new GridBagLayout());
content.setBorder(new EmptyBorder(32, 32, 32, 32));
content.add(cb);
frame.setContentPane(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MyKeySelectionManager implements KeySelectionManager {
private Timer timeout;
private StringBuilder pattern = new StringBuilder(32);
public MyKeySelectionManager() {
timeout = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
pattern.delete(0, pattern.length());
}
});
timeout.setRepeats(false);
}
protected int indexOf(Object item, ComboBoxModel<?> model) {
for (int index = 0; index < model.getSize(); index++) {
if (model.getElementAt(index) == item) {
return index;
}
}
return -1;
}
@Override
public int selectionForKey(char aKey, ComboBoxModel<?> model) {
timeout.stop();
pattern.append(Character.toLowerCase(aKey));
String match = pattern.toString();
for (int index = 0; index < model.getSize(); index++) {
String text = model.getElementAt(index).toString().toLowerCase();
if (text.startsWith(match)) {
timeout.start();
return index;
}
}
timeout.start();
return -1;
}
}
}
别忘了看看JComboBox#setKeySelectionManager
,了解更多详细信息