将ObservableList <textfield>绑定到ListProperty <string> JFX

时间:2016-06-14 07:51:48

标签: java data-binding javafx

鉴于

我有一个模型类Model,其中包含以下字段:

StringProperty stringProperty; ListProperty<String> listOfStringsProperty

我有一个视图类View extends VBox,其中包含以下内容:

TextField stringTextField; TextFieldList stringsTextFieldList;

TextFieldList extends VBox是我创建的一个自定义类,它使用nice +和 - 按钮处理多个TextFields以添加和删除输入文本字段。

TextFieldList类包含字段ObservableList<Node> inputTextFields,我可以通过方法调用List<String> getData()

从这些InputTextFields获取数据


问题

我能够做到以下几点:

stringTextField.textProperty().bindBidirectional(model.getStringProperty());

为了将stringTextFieldView的结果与stringProperty中的Model

绑定

我需要做一些像

这样的事情
stringsTextFieldList.listProperty().bindBidirectional(model.getListOfStringsProperty());

我该怎么做?

如果此设计不起作用,那么您如何建议我修复它?是否有内置类与TextFieldList相同,而是extends Control

2 个答案:

答案 0 :(得分:0)

你可以使用 Bindings.bindContent(List list1, ObservableList list2)

这是一个特殊的绑定,使列表与可观察列表保持同步。请记住,这不是双向的。

如果您想要双向性,则应使用失效侦听器或更改侦听器来检测更改并手动同步列表。您可能需要一些原始锁定机制来防止堆栈溢出。

答案 1 :(得分:0)

如果您决定自行控制,则应创建“手动绑定”,这意味着在输入ObservableList中添加了ListChangeListener,然后您将处理Change示例:检查是否添加,删除或更新了新项目,并相应地维护TextField s。这是可能的,但我的答案主要是提出一个现有的控件来重复使用,而不是创建自己的控件。

所以如果你不想重新发明轮子:

我不知道您的确切用例,但重用实际支持数据模型的控件可能是合理的,例如ListView

在示例中,我将Model类修改为ObservableList<StringProperty>而不是ListProperty<String>(注意:列表中也可能只有String个对象,我只是修改它以使绑定真正清楚)。我添加了ListView并使用setCellFactory绘制TextField作为列表中的元素,这些元素双向绑定到列表中的相应StringProperty。我还添加了几个按钮来添加和删除元素,还添加了一个按钮来打印模型的当前内容。

示例:

Model.java

public class Model {

    public ObservableList<StringProperty> listOfStringsProperty;

    public Model(){
        listOfStringsProperty = FXCollections.observableArrayList();    
    }

}

Main.java

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root,400,400);      

            Model m = new Model();
            m.listOfStringsProperty.addAll(new SimpleStringProperty("First"),
                    new SimpleStringProperty("Second"),
                    new SimpleStringProperty("Third"));

            ListView<StringProperty> lv = new ListView<StringProperty>();
            lv.setCellFactory(new Callback<ListView<StringProperty>, ListCell<StringProperty>>() {

                @Override
                public ListCell<StringProperty> call(ListView<StringProperty> param) {
                    return new ListCell<StringProperty>(){

                        @Override
                        protected void updateItem(StringProperty item, boolean empty) {

                            super.updateItem(item, empty);

                            if(item == null){
                                setText(null);
                                setGraphic(null);
                                return;
                            }

                            TextField tf = new TextField();
                            tf.textProperty().bindBidirectional(item);
                            setGraphic(tf);
                        }
                    };
                }
            });


            lv.setItems(m.listOfStringsProperty);

            root.setCenter(lv);

            // Control buttons
            HBox hbox = new HBox();
            Button buttonAdd = new Button("Add");
            buttonAdd.setOnAction(e -> m.listOfStringsProperty.add(new SimpleStringProperty("")));

            Button buttonRemove = new Button("Remove last");
            buttonRemove.setOnAction(e -> m.listOfStringsProperty.remove(m.listOfStringsProperty.size()-1));

            Button buttonPrintModel = new Button("Print model");
            buttonPrintModel.setOnAction(e -> System.out.println(m.listOfStringsProperty.toString()));

            hbox.getChildren().addAll(buttonAdd, buttonRemove, buttonPrintModel);


            root.setBottom(hbox);

            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

这将生成以下窗口:

enter image description here