我有一个组合框cb
和一个ObservableList<StringProperty> data
我已将cb
的{{1}}绑定到Items
,如下所示:
data
假设Bindings.bindContent(cb.getItems(), data);
包含以下内容:data
当我更改str1, str2, str3, str4
时,组合框会毫无问题地获取新列表。
但是,如果在data
中选择了str3
并且我在数据中将cb
的值更改为str3
,则该更改不会显示在cb中。有时显示的列表也是错误的(它显示str3而不是NewStr3),尽管它引用的基础数据是正确的。
如何在更改基础模型时强制组合框显示新值?
答案 0 :(得分:2)
组合框中的所选项目不需要是组合框项目列表的元素。 (例如,在可编辑的组合框中,您可以键入不在列表中的项目。)如果您从这个角度考虑您的示例,那么它的行为与您描述的一样并不奇怪。
如果要在该列表可能更改时强制将所选值作为基础列表的元素,则需要定义如果列表以不再包含所选项的方式更改所选项的更改方式item(你将如何做到这一点并不明显,可能取决于你的应用程序逻辑)。一旦知道了自己想做什么,就可以使用ListChangeListener
:
cb.getItems().addListener((ListChangeListener.Change change) -> {
String newSelectedItem = ... ; // figure item that should be selected instead
cb.setValue(newSelectedItem);
});
最简单的实现只是cb.setValue(null);
,这意味着如果列表发生更改,则不会选择任何项目,以便它不再包含当前选定的项目。
答案 1 :(得分:-1)
糟糕...误读了comboBox的choiceBox - 虽然这个答案的基础知识同时适用于combo和choiceBox,但我没有定制的ComboBoxX - 但是: - )
基本上,SelectionModel负责更新项目的更改。在核心中实现的预期行为是完全清除选择 - 即,使selectedItem为null并将selectedIndex设置为-1 - 如果旧项是selectedItem并被替换或删除。自定义行为的典型解决方案是实现自定义选择模型并进行设置:
/**
* A SelectionModel that updates the selectedItem if it is contained in
* the data list and was replaced/updated.
*
* @author Jeanette Winzenburg, Berlin
*/
public static class MySelectionModel<T> extends ChoiceBoxSelectionModel<T> {
public MySelectionModel(ChoiceBoxX<T> cb) {
super(cb);
}
@Override
protected void itemsChanged(Change<? extends T> c) {
// selection is in list
if (getSelectedIndex() != -1) {
while (c.next()) {
if (c.wasReplaced() || c.wasUpdated()) {
if (getSelectedIndex() >= c.getFrom()
&& getSelectedIndex() < c.getTo()) {
setSelectedItem(getModelItem(getSelectedIndex()));
return;
}
}
}
}
// super expects a clean change
c.reset();
super.itemsChanged(c);
}
}
// usage
myChoiceBox.setSelectionModel(new MySelectionModel(myChoiceBox));
不幸的是,核心选择框并没有遵守规则 - 它严重干扰了模型的职责(可能是因为模型实施不能胜任其职责),这需要完全重新编写整个协作者堆栈(choiceBox,-skin,复制-behaviour),例如ChoiceBoxX - 我只是学习了一点,尝试删除它的一些气味并修复一些错误。