【发布时间】:2018-11-05 17:32:37
【问题描述】:
编辑: 我正在尝试构建一个具有搜索功能的组合框,这就是我想出的:
public class SearchableComboBox<T> extends ComboBox<T> {
private ObservableList<T> filteredItems;
private ObservableList<T> originalItems;
private T selectedItem;
private StringProperty filter = new SimpleStringProperty("");
public SearchableComboBox () {
this.setTooltip(new Tooltip());
this.setOnKeyPressed(this::handleOnKeyPressed);
this.getTooltip().textProperty().bind(filter);
this.showingProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
// If user "closes" the ComboBox dropdown list: reset filter, reset list to the full original list, hide tooltip
if (newValue == false) {
filter.setValue("");;
setItems(originalItems);
getTooltip().hide();
// If user opens the combobox dropdown list: get a copy of the items and show tooltip
} else {
originalItems = getItems();
Window stage = getScene().getWindow();
getTooltip().show(stage);
}
}
});
}
public void handleOnKeyPressed(KeyEvent e) {
//Only execute if the dropdown list of the combobox is opened
if (this.showingProperty().getValue() == true) {
// Get key and add it to the filter string
String c = e.getText();
filter.setValue(filter.getValue() + c);
//Filter out objects that dont contain the filter
this.filteredItems = this.originalItems.filtered(a -> this.getConverter().toString(a).toLowerCase().contains(filter.getValue().toLowerCase()));
//Set the items of the combox to the filtered list
this.setItems(filteredItems);
}
}
这个想法很简单:只要打开组合框的下拉列表,我就会监听按键并将字符添加到过滤器中。使用这些过滤器,组合框的项目列表被过滤为仅包含项目的列表,这些项目包含过滤器字符串。然后我使用 setItems 将项目列表设置为我的过滤列表。我的问题是,组合框的 valueProperty 发生了变化,但我希望所选对象保持不变,直到用户从下拉列表中选择另一个对象。我在 ValueProperty 中添加了一个 ChangeListener:
public void changed(ObservableValue<? extends PersonalModel> observable, PersonalModel oldValue,
PersonalModel newValue) {
System.out.println("Value changed");
if (newValue == null) {
System.out.println(newValue);
} else {
System.out.println(personalauswahl.getConverter().toString(newValue));
labelArbeitszeitAnzeige.setText(String.valueOf(newValue.getArbeitszeit()));
}
}
});
当值改变时,控制台看起来像这样:
值改变了
Andersen, Wiebke(对象的字符串表示)
或者像这样:
值改变了
null(对象为null)
基本上有 3 种情况正在发生。首先是我打开下拉列表,不要选择一个项目并输入我的过滤器。然后我选择一个项目,我的打印件会显示给我:
值改变了
安徒生,维布克
值改变了
空
值改变了
安徒生,维布克
第二种情况是我打开下拉列表并选择一个项目。我现在继续输入过滤器,所选项目包含过滤器。我的照片会告诉我这个:
值改变了
空
值改变了
安徒生,维布克
每次我按下一个键,当我选择 Andersen 时,Wiebke 再次/关闭下拉列表。
第三种情况是选择一个项目,然后继续输入所选项目不包含的过滤器。一旦所选项目不再包含过滤器,valueProperty 的值就会更改为 null。如果我选择一个新项目,那么我会得到这个:
值改变了
Budziszewski,卡琳
值改变了
空
值改变了
Budziszewski,卡琳
我想要的是在用户从下拉列表中选择一个新项目之前,ValueProperty 不会改变。此外,我真的很想知道为什么 valueproperty 对我来说一直在变化。特别是因为我真的不认为我的解决方案与 Zephyr 提供的解决方案之间存在根本区别。我们都使用过滤器字符串过滤原始列表,然后使用 setItems() 将 Combobox 的列表设置为新过滤的列表。正如下面评论中提到的,我什至不能使用他的解决方案,因为我无法让 Combobox 的 setEditable 工作:
当我尝试 personalauswahl.setEditable(true);我得到原因:de.statistik_nord.klr.controller.EingabeController$1.toString(EingabeController.java:93) 的 java.lang.NullPointerException de.statistik_nord.klr.controller.EingabeController$1.toString(EingabeController.java:1)指向这行代码:return object.getName() +", " + object.getVorname();
【问题讨论】:
-
只是一个评论:如果您除了配置之外什么都不做,就没有理由扩展组合 - 所以不要
-
没有吗?如果我想在我的项目中多次使用它,我每次都必须进行配置,不是吗?这样我就可以实例化我的类而不是组合框并完成它?您将如何将其用于多次使用?
-
您将配置添加到返回配置的
ComboBox的方法中。将该方法公开,您现在就有了一个可重复使用的ComboBox,而无需扩展它。
标签: java javafx combobox listener