【问题标题】:dynamically add textfields using listeners使用侦听器动态添加文本字段
【发布时间】:2018-04-24 14:37:28
【问题描述】:

我正在尝试使用 javafx 在 Android 手机上编写类似于联系人应用程序的程序。在 fxml 文件中,我有一个 VBox,其中包含三个文本字段,前两个字段用于名字和姓氏,第三个字段用于数字。

现在我想要程序做的是当数字的文本字段被填充一个字符时,另一个文本字段将自动添加到 VBox。 (换个号码)。

我希望下一个字段也发生同样的事情。以及随后的任何其他字段,因此它具有递归形式。

现在我知道的唯一可能实现此目的的方法是使用侦听器,但我不知道如何创建这样的递归侦听器。并且一旦完成其工作,就必须删除旧字段的侦听器,因此在旧字段中键入内容时它不会不断创建新字段。但是当你在里面时你不能移除一个监听器。

有没有办法做到这一点?

【问题讨论】:

    标签: java javafx


    【解决方案1】:

    lambda 表达式不能引用自身,但匿名内部类可以,因此如果您将侦听器实现为匿名内部类,则可以实现您想要做的事情:

    import javafx.application.Application;
    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    import javafx.scene.Scene;
    import javafx.scene.control.ScrollPane;
    import javafx.scene.control.TextField;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    public class DynamicTextFields extends Application {
    
        private TextField lastTextField ;
    
        @Override
        public void start(Stage primaryStage) {
            lastTextField = new TextField();
            VBox vbox = new VBox(5, lastTextField);
            ChangeListener<String> textFieldListener = new ChangeListener<String>() {
    
                @Override
                public void changed(ObservableValue<? extends String> obs, String oldValue, String newValue) {
                    lastTextField.textProperty().removeListener(this);
                    lastTextField = new TextField();
                    lastTextField.textProperty().addListener(this);
                    vbox.getChildren().add(lastTextField);
                }
    
            };
            lastTextField.textProperty().addListener(textFieldListener);
    
            Scene scene = new Scene(new ScrollPane(vbox), 400, 400);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    【讨论】:

      【解决方案2】:

      ChangeListener 注册到TextFields 的text 属性,每次文本从空变为非空或相反时,根据索引添加/删除TextField

      public void addTextField(Pane parent) {
          TextField textField = new TextField();
          textField.textProperty().addListener((o, oldValue, newValue) -> {
              boolean wasEmpty = oldValue.isEmpty();
              boolean isEmpty = newValue.isEmpty();
      
              if (wasEmpty != isEmpty) {
                  if (wasEmpty) {
                      // append textfield if last becomes non-empty
                      if (parent.getChildren().get(parent.getChildren().size() - 1) == textField) {
                          addTextField(parent);
                      }
                  } else {
                      int tfIndex = parent.getChildren().indexOf(textField);
                      if (tfIndex < parent.getChildren().size() - 1) {
                          // remove textfield if this is not the last one
                          parent.getChildren().remove(tfIndex);
                          parent.getChildren().get(tfIndex).requestFocus();
                      }
                  }
              }
          });
      
          parent.getChildren().add(textField);
      }
      
      VBox root = new VBox();
      addTextField(root);
      

      【讨论】:

        猜你喜欢
        • 2018-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-01
        • 2013-09-10
        相关资源
        最近更新 更多