4

当我更改底层可观察数组列表时,图形选择框不会更新。必须有比我在这里看到的建议更新 的解决方案,例如:JavaFX:如果 ObservableList 的元素发生变化,则更新 ListView

    int selected = productsChoiceBox.getSelectionModel().getSelectedIndex();
    Product prod = products.get(selected);
    prod.setName(productName.getText());
    prod.setUrl(productUrl.getText());

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

4

2 回答 2

4

“标准”答案是使用 anObservableListextractor. 但是,当我对此进行测试时,它的行为并不像宣传的那样,而且似乎存在一个错误(我的猜测是ChoiceBox没有正确处理wasUpdated在其 中触发的类型更改ListChangedListener),我将在 JIRA 报告。更新:在https://javafx-jira.kenai.com/browse/RT-38394提交报告

工厂方法FXCollections.observableArrayList(Callback)创建一个(空的)可观察数组列表。提供Callback的是将列表中的每个元素映射到 s 数组的函数Observable。该列表使用这些可观察对象注册侦听器,如果这些属性发生更改,则该列表会向其侦听器触发更新通知。

但是,这会产生奇怪的结果 a ChoiceBox;一种可能的解决方法是使用ComboBox似乎可以正常工作的 a 。

这是一些示例代码。选择一个项目:然后在文本字段中输入并按 Enter 键更改所选项目的名称。更改ChoiceBoxComboBox查看正确的行为:

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);
    }
}
于 2014-08-22T01:25:02.463 回答
2

正确和正确的答案来自 James_D,但如果您真的想使用 ChoiceBox,请尝试添加和删除:

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

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

于 2014-08-22T02:02:43.713 回答