我扩展了JComboBox以添加自动完成功能。这是代码:
public class AutocompleteJComboBox extends JComboBox{
static final long serialVersionUID = 4321421L;
private final Searchable<String,String> searchable;
/**
* Constructs a new object based upon the parameter searchable
* @param s
*/
public AutocompleteJComboBox(Searchable<String,String> s){
super();
this.searchable = s;
setEditable(true);
Component c = getEditor().getEditorComponent();
if (c instanceof JTextComponent){
final JTextComponent tc = (JTextComponent)c;
tc.getDocument().addDocumentListener(new DocumentListener(){
@Override
public void changedUpdate(DocumentEvent arg0) {}
@Override
public void insertUpdate(DocumentEvent arg0) {
update();
}
@Override
public void removeUpdate(DocumentEvent arg0) {
update();
}
public void update(){
//perform separately, as listener conflicts between the editing component
//and JComboBox will result in an IllegalStateException due to editing
//the component when it is locked.
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
List<String> founds = new ArrayList<String>(searchable.search(tc.getText()));
Set<String> foundSet = new HashSet<String>();
for ( String s : founds ){
foundSet.add(s.toLowerCase());
}
Collections.sort(founds);//sort alphabetically
setEditable(false);
removeAllItems();
//if founds contains the search text, then only add once.
if ( !foundSet.contains( tc.getText().toLowerCase()) ){
addItem( tc.getText() );
}
for (String s : founds) {
addItem(s);
}
setEditable(true);
setPopupVisible(true);
}
});
}
});
//When the text component changes, focus is gained
//and the menu disappears. To account for this, whenever the focus
//is gained by the JTextComponent and it has searchable values, we show the popup.
tc.addFocusListener(new FocusListener(){
@Override
public void focusGained(FocusEvent arg0) {
System.out.println("Focus gained");
if ( tc.getText().length() > 0 ){
setPopupVisible(true);
}
tc.requestFocusInWindow();
}
@Override
public void focusLost(FocusEvent arg0) {
System.out.println("Focus lost");
}
});
}else{
throw new IllegalStateException("Editing component is not a JTextComponent!");
}
}
}
现在,自动完成部分工作正常。问题是,在我输入一个字符后,它会失去焦点(焦点转到我的其他UI元素,一个普通的JTextField)。我必须提一下,如果UI只包含这个组合框,它可以完美地工作,不会丢失焦点(因为我没有其他元素,我认为)。
知道我在这里做错了什么吗?感谢。
答案 0 :(得分:0)
如果还不晚,并且对于每个人都在努力解决这个问题,我在requestFocus()
方法的末尾添加了update()
。这是一种解决方法,但似乎工作正常。
此自动完成组合框实现的另一个补充是添加
putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
在构造函数中,使您可以使用向上nad向下箭头键循环使用弹出项目,而无需更改组合框中的输入。