【问题标题】:JavaFX binding between TextField and a propertyTextField 和属性之间的 JavaFX 绑定
【发布时间】:2014-05-28 08:20:06
【问题描述】:

如果您在 JavaFX TextField 和属性之间创建绑定,则此绑定在每次击键时都会失效,从而导致文本发生更改。

如果您有一个绑定链,则默认行为可能会导致问题,因为在中间编辑值可能无效。

好的,我知道我可以创建从属性到文本字段的单向绑定,并注册一个更改侦听器,以便在光标离开字段时获得通知,并在必要时手动更新属性。

是否有一种简单、优雅的方法来更改此行为,以便仅在编辑完成时绑定无效,例如光标何时离开字段?

谢谢

【问题讨论】:

    标签: java binding javafx textfield


    【解决方案1】:

    我认为您已经描述了完成此操作的唯一方法。这是我能看到的最简洁的实现方式(使用 Java 8,但如果需要,可以很容易地将 lambda 转换回与 JavaFX 2.2 兼容):

    import javafx.application.Application;
    import javafx.beans.binding.Bindings;
    import javafx.beans.binding.StringBinding;
    import javafx.event.ActionEvent;
    import javafx.scene.Scene;
    import javafx.scene.control.TextField;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
        public class CommitBoundTextField extends Application {
    
            @Override
            public void start(Stage primaryStage) {
                TextField tf1 = new TextField();
                createCommitBinding(tf1).addListener((obs, oldText, newText) -> 
                    System.out.printf("Text 1 changed from \"%s\" to \"%s\"%n", oldText, newText));
                TextField tf2 = new TextField();
                createCommitBinding(tf2).addListener((obs, oldText, newText) -> 
                    System.out.printf("Text 2 changed from \"%s\" to \"%s\"%n", oldText, newText));
                VBox root = new VBox(5, tf1, tf2);
                Scene scene = new Scene(root, 250, 100);
                primaryStage.setScene(scene);
                primaryStage.show();
            }
    
            private StringBinding createCommitBinding(TextField textField) {
                StringBinding binding = Bindings.createStringBinding(() -> textField.getText());
                textField.addEventHandler(ActionEvent.ACTION, evt -> binding.invalidate());
                textField.focusedProperty().addListener((obs, wasFocused, isFocused)-> {
                    if (! isFocused) binding.invalidate();
                });
                return binding ;
            }
    
            public static void main(String[] args) {
                launch(args);
            }
        }
    

    【讨论】:

      【解决方案2】:

      我意识到我的回复有点晚了,但我认为这可能对某人有用。

      在使用TextFields 时,我经常附上TextFormatter 来帮助验证条目。您可以将侦听器附加到格式化程序的valueProperty。该属性在提交文本时更新,而不是在每次击键时更新。

      这是我正在谈论的使用专门用于整数输入的TextField 的示例。当您在文本字段中进行编辑时,当您点击 Enter、单击按钮失去焦点、切换到其他窗口等时,更改将反映在 Label 中。

      import javafx.application.Application;
      import javafx.beans.binding.StringBinding;
      import javafx.beans.property.IntegerProperty;
      import javafx.beans.property.SimpleIntegerProperty;
      import javafx.beans.value.ObservableValue;
      import javafx.geometry.Insets;
      import javafx.geometry.Pos;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.Label;
      import javafx.scene.control.TextField;
      import javafx.scene.control.TextFormatter;
      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;
      import javafx.util.converter.IntegerStringConverter;
      
      class IntTextField extends TextField {
      
          private final IntegerProperty value;
          TextFormatter<Integer> formatter;
      
          public double getValue() {
              return value.getValue();
          }
      
          public void setValue(int newValue) {
              value.setValue(newValue);
          }
      
          public IntegerProperty valueProperty() {
              return value;
          }
          
          public StringBinding getStringBinding () {
              return value.asString();
          }
      
          IntTextField(int initValue) {
              value = new SimpleIntegerProperty(initValue);
              setText(initValue + "");
              formatter = new TextFormatter(new IntegerStringConverter(), initValue);
              formatter.valueProperty().addListener((ObservableValue<? extends Integer> obs,
                      Integer oldValue, Integer newValue) -> value.setValue(newValue));
              setTextFormatter(formatter);
          }
      
          IntTextField() {
              this(0);
          }
      }
      
      public class TFBindingDemo extends Application {
      
          @Override
          public void start(Stage stage) {
              stage.setTitle("TFBindingDemo");
              IntTextField intTextField = new IntTextField(12345);
              intTextField.setMaxWidth(150);
              Label label = new Label("Type in the TextField");
              label.textProperty().bind(intTextField.getStringBinding());
              Button removeFocusButton = new Button("Click Here to Remove Focus");
              VBox root = new VBox(20, intTextField, label, removeFocusButton);
              root.setAlignment(Pos.CENTER);
              root.setPadding(new Insets(20));
              Scene scene = new Scene(root, 325, 200);
              stage.setScene(scene);
              stage.show();
          }
      
          public static void main(String[] args) {
              launch();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-25
        • 1970-01-01
        • 2016-09-17
        • 1970-01-01
        • 2013-06-26
        • 1970-01-01
        • 2023-03-21
        • 1970-01-01
        相关资源
        最近更新 更多