Java 是否有人成功地为列表单元格自动完成组合框?
作为独立元素,解决方案可以正常工作 但在自定义ListCell(从ComboBoxListCell源镜像)中,有时会给出:Java 是否有人成功地为列表单元格自动完成组合框?,java,listview,combobox,autocomplete,javafx-8,Java,Listview,Combobox,Autocomplete,Javafx 8,作为独立元素,解决方案可以正常工作 但在自定义ListCell(从ComboBoxListCell源镜像)中,有时会给出: Exception in thread "JavaFX Application Thread" java.lang.NullPointerException at com.sun.javafx.scene.control.skin.ComboBoxPopupControl.positionAndShowPopup(ComboBoxPopupControl.java:100)
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at com.sun.javafx.scene.control.skin.ComboBoxPopupControl.positionAndShowPopup(ComboBoxPopupControl.java:100)
at com.sun.javafx.scene.control.skin.ComboBoxPopupControl.show(ComboBoxPopupControl.java:74)
at com.sun.javafx.scene.control.skin.ComboBoxBaseSkin.handleControlPropertyChanged(ComboBoxBaseSkin.java:115)
at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.handleControlPropertyChanged(ComboBoxListViewSkin.java:245)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$2.call(BehaviorSkinBase.java:189)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$2.call(BehaviorSkinBase.java:187)
at com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler$1.changed(MultiplePropertyChangeListenerHandler.java:55)
at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:176)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
at javafx.beans.property.ReadOnlyBooleanWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyBooleanWrapper.java:178)
at javafx.beans.property.ReadOnlyBooleanWrapper$ReadOnlyPropertyImpl.access$100(ReadOnlyBooleanWrapper.java:148)
at javafx.beans.property.ReadOnlyBooleanWrapper.fireValueChangedEvent(ReadOnlyBooleanWrapper.java:144)
at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:143)
at javafx.scene.control.ComboBoxBase.setShowing(ComboBoxBase.java:202)
at javafx.scene.control.ComboBoxBase.show(ComboBoxBase.java:407)
ComboBox的show()方法似乎可以在JavaFX代码中生成NPE
自定义ComboBoxListCell仅在startEdit()中不同:
@Override public void startEdit(){
如果(!isEditable()| |!getListView().isEditable()){
返回;
}
如果(组合框==null){
comboBox=createComboBox(这个,items,converterProperty());
//唯一的特殊字符串
handler=new autocompleteComboxListener(组合框);
comboBox.editableProperty().bind(comboBoxEditableProperty());
}
comboBox.getSelectionModel().select(getItem());
super.startEdit();
if(isEditing()){
setText(空);
设置图形(组合框);
}
}
AutoCompleteComboxListener的代码,提供NPE:
@Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.UP) {
caretPos = -1;
moveCaret(comboBox.getEditor().getText().length());
return;
} else if(event.getCode() == KeyCode.DOWN) {
if(!comboBox.isShowing()) {
comboBox.show();
}
caretPos = -1;
moveCaret(comboBox.getEditor().getText().length());
return;
} else if(event.getCode() == KeyCode.BACK_SPACE) {
moveCaretToPos = true;
caretPos = comboBox.getEditor().getCaretPosition();
} else if(event.getCode() == KeyCode.DELETE) {
moveCaretToPos = true;
caretPos = comboBox.getEditor().getCaretPosition();
}
if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.LEFT
|| event.isControlDown() || event.getCode() == KeyCode.HOME
|| event.getCode() == KeyCode.END || event.getCode() == KeyCode.TAB) {
return;
}
ObservableList list = FXCollections.observableArrayList();
for (int i=0; i<data.size(); i++) {
if(data.get(i).toString().toLowerCase().startsWith(
AutoCompleteComboBoxListener.this.comboBox
.getEditor().getText().toLowerCase())) {
list.add(data.get(i));
}
}
String t = comboBox.getEditor().getText();
comboBox.setItems(list);
comboBox.getEditor().setText(t);
if(!moveCaretToPos) {
caretPos = -1;
}
moveCaret(t.length());
if(!list.isEmpty()) {
//This gives NPE inside JavaFX API
comboBox.show();
}
}
@覆盖
公共无效句柄(KeyEvent事件){
if(event.getCode()==KeyCode.UP){
caretPos=-1;
moveCaret(comboBox.getEditor().getText().length());
返回;
}else if(event.getCode()==KeyCode.DOWN){
如果(!comboBox.isShowing()){
comboBox.show();
}
caretPos=-1;
moveCaret(comboBox.getEditor().getText().length());
返回;
}else if(event.getCode()==KeyCode.BACK\u空格){
MoveCareTopos=真;
caretPos=comboBox.getEditor().getCaretPosition();
}else if(event.getCode()==KeyCode.DELETE){
MoveCareTopos=真;
caretPos=comboBox.getEditor().getCaretPosition();
}
如果(event.getCode()==KeyCode.RIGHT | | event.getCode()==KeyCode.LEFT
||event.isControlDown()| | event.getCode()==KeyCode.HOME
||event.getCode()==KeyCode.END | | event.getCode()==KeyCode.TAB){
返回;
}
ObservableList=FXCollections.observableArrayList();
对于(int i=0;iOk),问题是setItems将当前选择跳过到-1,然后ListCell将该事实视为需要提交新值(null)(如果当前选择!=-1)。提交之后,comboBox将不显示任何内容,因为它处于非编辑状态
因此,这是一个设计问题,而不是一个bug。ComboBoxListCell代码无法在没有特别注意的情况下动态更改项目。您找到解决方案了吗?
@Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.UP) {
caretPos = -1;
moveCaret(comboBox.getEditor().getText().length());
return;
} else if(event.getCode() == KeyCode.DOWN) {
if(!comboBox.isShowing()) {
comboBox.show();
}
caretPos = -1;
moveCaret(comboBox.getEditor().getText().length());
return;
} else if(event.getCode() == KeyCode.BACK_SPACE) {
moveCaretToPos = true;
caretPos = comboBox.getEditor().getCaretPosition();
} else if(event.getCode() == KeyCode.DELETE) {
moveCaretToPos = true;
caretPos = comboBox.getEditor().getCaretPosition();
}
if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.LEFT
|| event.isControlDown() || event.getCode() == KeyCode.HOME
|| event.getCode() == KeyCode.END || event.getCode() == KeyCode.TAB) {
return;
}
ObservableList list = FXCollections.observableArrayList();
for (int i=0; i<data.size(); i++) {
if(data.get(i).toString().toLowerCase().startsWith(
AutoCompleteComboBoxListener.this.comboBox
.getEditor().getText().toLowerCase())) {
list.add(data.get(i));
}
}
String t = comboBox.getEditor().getText();
comboBox.setItems(list);
comboBox.getEditor().setText(t);
if(!moveCaretToPos) {
caretPos = -1;
}
moveCaret(t.length());
if(!list.isEmpty()) {
//This gives NPE inside JavaFX API
comboBox.show();
}
}