JavaFX Choiceox更改不更新图形

JavaFX Choiceox更改不更新图形,java,javafx,observablelist,Java,Javafx,Observablelist,当我更改基础可观察数组列表时,图形选择框不会更新。一定有比我在这里看到的建议更新的解决方案,例如: 有什么想法吗?我希望避免删除和添加。标准答案是使用可观察列表和提取器。然而,当我测试这一点时,它的行为并不像广告中所说的那样,而且似乎有一个bug(我猜ChoiceBox没有正确处理wasdupdated在其ListChangedListener中触发的类型更改),我将在JIRA报告更新:在 工厂方法创建一个(空)可观察数组列表。提供的回调是一个函数,它将列表中的每个元素映射到可观察的数组。列表

当我更改基础可观察数组列表时,图形选择框不会更新。一定有比我在这里看到的建议更新的解决方案,例如:

有什么想法吗?我希望避免删除和添加。

标准答案是使用
可观察列表
提取器
。然而,当我测试这一点时,它的行为并不像广告中所说的那样,而且似乎有一个bug(我猜
ChoiceBox
没有正确处理
wasdupdated
在其
ListChangedListener
中触发的类型更改),我将在JIRA报告更新:

工厂方法创建一个(空)可观察数组列表。提供的
回调
是一个函数,它将列表中的每个元素映射到可观察的
数组。列表用这些可观察的对象注册侦听器,如果这些属性发生更改,列表将向其侦听器发出更新通知

然而,这在
选择框
中产生了奇怪的结果;一种可能的解决方法是使用一个似乎工作正常的组合框

下面是一些示例代码。选择项目:然后在文本字段中键入并按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);
    }
}
import java.util.stream.collector;
导入java.util.stream.IntStream;
导入javafx.application.application;
导入javafx.beans.Observable;
导入javafx.beans.binding.Bindings;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.property.StringProperty;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.scene.scene;
导入javafx.scene.control.ChoiceBox;
导入javafx.scene.control.TextField;
导入javafx.scene.layout.BorderPane;
导入javafx.stage.stage;
公共类ChoiceBoxUpdateExample扩展应用程序{
@凌驾
公共无效开始(阶段primaryStage){
ChoiceBox ChoiceBox=新建ChoiceBox();
ObservableList items=FXCollections.observableArrayList(
item->newobservable[]{item.nameProperty()});//提取器
items.addAll(
IntStream.rangeClosed(1,10)
.mapToObj(i->新项目(“项目”+i))
.collect(Collectors.toList());
choiceBox.setItems(项目);
TextField changeSelectedField=新建TextField();
changeSelectedField.disableProperty()
.bind(Bindings.isNull(choiceBox.getSelectionModel().selectedItemProperty());
changeSelectedField.setOnAction(事件->
choiceBox.getSelectionModel().getSelectedItem().setName(changeSelectedField.getText());
BorderPane根=新的BorderPane();
root.setTop(选择框);
root.setBottom(changeSelectedField);
场景=新场景(根,250,150);
初级阶段。场景(场景);
primaryStage.show();
}
公共静态类项{
public final StringProperty name=new SimpleStringProperty();
公共字符串属性nameProperty(){
返回名称;
}
公共最终字符串getName(){
返回nameProperty().get();
}
公共最终无效集合名(字符串名){
nameProperty().set(名称);
}
公共项(字符串名称){
集合名(名称);
}
@凌驾
公共字符串toString(){
返回getName();
}
}
公共静态void main(字符串[]args){
发射(args);
}
}

正确正确的答案来自James\u D,但如果您确实想使用ChoiceBox,请尝试添加和删除:

    int selected = productsChoiceBox.getSelectionModel().getSelectedIndex();
    products.remove(selected);
    products.add(selected, prod);

我不相信这是正确的方法,但我测试了它,它确实有效。ChoiceBox保留在已删除和选定的索引上,看起来会更新。

我同意这也是一个好的观点。绝对不优雅,我只是想让人们知道它确实有效,但我同意,这不是理想的选择。当然,完成了。很抱歉。
    int selected = productsChoiceBox.getSelectionModel().getSelectedIndex();
    products.remove(selected);
    products.add(selected, prod);