JComboBox 在输入一个字符后失去焦点
JComboBox loses focus after typing one character
我扩展了 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 只包含这个组合框,它会完美地工作,不会丢失焦点(因为没有其他元素,我假设)。
知道我这里可能做错了什么吗?谢谢
如果还不算太晚,并且为了每个为此苦苦挣扎的人,我在 update()
方法的末尾添加了 requestFocus()
。这是一种解决方法,但似乎工作正常。
此自动完成组合框实现的另一个添加是添加
putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
在构造函数中,它使您可以使用向上和向下箭头键循环浏览弹出项,而无需更改组合框中的输入。
我扩展了 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 只包含这个组合框,它会完美地工作,不会丢失焦点(因为没有其他元素,我假设)。
知道我这里可能做错了什么吗?谢谢
如果还不算太晚,并且为了每个为此苦苦挣扎的人,我在 update()
方法的末尾添加了 requestFocus()
。这是一种解决方法,但似乎工作正常。
此自动完成组合框实现的另一个添加是添加
putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
在构造函数中,它使您可以使用向上和向下箭头键循环浏览弹出项,而无需更改组合框中的输入。