【问题标题】:Bind ObservableList<TextField> to ListProperty<String> JFX将 ObservableList<TextField> 绑定到 ListProperty<String> JFX
【发布时间】:2016-10-14 20:03:41
【问题描述】:

给定

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

StringProperty stringProperty; ListProperty&lt;String&gt; listOfStringsProperty

我有一个视图类 View extends VBox,它具有以下内容:

TextField stringTextField; TextFieldList stringsTextFieldList;

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

TextFieldList 类包含字段 ObservableList&lt;Node&gt; inputTextFields,我可以通过方法调用 List&lt;String&gt; getData() 从这些 InputTextField 中获取数据


问题

我能够做到以下几点:

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

为了将View中的stringTextField的结果绑定到Model中的stringProperty

我需要做一些类似的事情

stringsTextFieldList.listProperty().bindBidirectional(model.getListOfStringsProperty());

我该怎么做?

如果这个设计不起作用,那么你建议我如何解决它?是否有一个与TextFieldList 功能相同但与extends Control 相同的内置类?

【问题讨论】:

    标签: java data-binding javafx


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

      因此,如果您不想重新发明轮子:

      我不知道你的确切用例,但也许重用一个实际支持数据模型的控件是合理的,比如ListView

      在示例中,我将 Model 类修改为具有 ObservableList&lt;StringProperty&gt; 而不是 ListProperty&lt;String&gt;(注意:也可以在列表中简单地包含 String 对象,我只是对其进行了修改以进行绑定真的很清楚)。我添加了一个ListView 并使用setCellFactoryTextFields 绘制为列表中的元素,这些元素双向绑定到列表中相应的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);
          }
      }
      

      这将产生以下窗口:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-08
        • 2019-01-18
        • 2018-01-11
        • 1970-01-01
        • 1970-01-01
        • 2015-10-14
        • 2019-12-25
        相关资源
        最近更新 更多