“标准”答案是使用 anObservableList
和extractor
. 但是,当我对此进行测试时,它的行为并不像宣传的那样,而且似乎存在一个错误(我的猜测是ChoiceBox
没有正确处理wasUpdated
在其 中触发的类型更改ListChangedListener
),我将在 JIRA 报告。更新:在https://javafx-jira.kenai.com/browse/RT-38394提交报告
工厂方法FXCollections.observableArrayList(Callback)
创建一个(空的)可观察数组列表。提供Callback
的是将列表中的每个元素映射到 s 数组的函数Observable
。该列表使用这些可观察对象注册侦听器,如果这些属性发生更改,则该列表会向其侦听器触发更新通知。
但是,这会产生奇怪的结果 a ChoiceBox
;一种可能的解决方法是使用ComboBox
似乎可以正常工作的 a 。
这是一些示例代码。选择一个项目:然后在文本字段中输入并按 Enter 键更改所选项目的名称。更改ChoiceBox
以ComboBox
查看正确的行为:
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class ChoiceBoxUpdateExample extends Application {
@Override
public void start(Stage primaryStage) {
ChoiceBox<Item> choiceBox = new ChoiceBox<>();
ObservableList<Item> items = FXCollections.observableArrayList(
item -> new Observable[] {item.nameProperty()}); // the extractor
items.addAll(
IntStream.rangeClosed(1, 10)
.mapToObj(i -> new Item("Item "+i))
.collect(Collectors.toList()));
choiceBox.setItems(items);
TextField changeSelectedField = new TextField();
changeSelectedField.disableProperty()
.bind(Bindings.isNull(choiceBox.getSelectionModel().selectedItemProperty()));
changeSelectedField.setOnAction(event ->
choiceBox.getSelectionModel().getSelectedItem().setName(changeSelectedField.getText()));
BorderPane root = new BorderPane();
root.setTop(choiceBox);
root.setBottom(changeSelectedField);
Scene scene = new Scene(root, 250, 150);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class Item {
public final StringProperty name = new SimpleStringProperty();
public StringProperty nameProperty() {
return name ;
}
public final String getName() {
return nameProperty().get();
}
public final void setName(String name) {
nameProperty().set(name);
}
public Item(String name) {
setName(name);
}
@Override
public String toString() {
return getName();
}
}
public static void main(String[] args) {
launch(args);
}
}