JavaFX bidirectional binding not working with the control becoming not editable

14,814

Bidirectional binding example:

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class JavaFXApplication10 extends Application {

    private Model model = new Model();

    @Override
    public void start(Stage primaryStage) {

        final TextField textField = new TextField();

        Bindings.bindBidirectional(textField.textProperty(), model.firstProperty());

        // Track the changes
        model.firstProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> arg0, String arg1, String arg2) {
                System.out.println("model old val: " + arg1);
                System.out.println("model new val: " + arg2);
                System.out.println();
            }
        });

        textField.textProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> arg0, String arg1, String arg2) {
                System.out.println("textField old val: " + arg1);
                System.out.println("textField new val: " + arg2);
                System.out.println();
            }
        });

        Button btn = new Button();
        btn.setText("Change the model's text");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                model.setFirst("changed from button action");
                System.out.println("Done.");
            }
        });

        BorderPane root = new BorderPane();
        root.setTop(textField);
        root.setBottom(btn);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }

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

    // Data Model
    public static class Model {

        StringProperty first = new SimpleStringProperty();
        //getter

        public String getFirst() {
            return first.get();
        }
        //setter

        public void setFirst(String first) {
            this.first.set(first);
        }
        //new "property" accessor

        public StringProperty firstProperty() {
            return first;
        }
    }
}

Bidirectional binding:
1 way - Text entered into textField will be reflected to the model's first stringProperty.
2nd contrary way - By clicking the button, you will notice that when model's first stringProperty is set, the textfield's text value will be also changed.

Share:
14,814
AgostinoX
Author by

AgostinoX

The quality of the examples is very important. A collection of good examples can replace an incomplete documentation. But each example should be short, only in this way it will be eloquent. The reader is making an effort to understand a concept. Not to debug a procedure!

Updated on June 26, 2022

Comments

  • AgostinoX
    AgostinoX almost 2 years

    Give a very elementary class (imports resolved into javafx packages):

    public class T07 extends Application implements Initializable{
    

    with some fields representing controls defined in an .fxml file:

    @FXML TextField text01;
    

    and a data model that uses Property wrappers in the most basic way:

    public static class DataModel {
    
        StringProperty first = new SimpleStringProperty();
        //getter
        public String getFirst() {return first.get();}
        //setter
        public void setFirst(String first) {this.first.set(first);}
        //new "property" accessor
        public StringProperty firstProperty() {return first;}
    
    }
    

    I try to bind the ui control with the data model inside the initialize:

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
    
       Bindings.bindBidirectional(text01.textProperty(), dm.firstProperty());
    
    }
    

    but doing so, i get a non-editable control. commenting out the Bindings.bindBidirectional line, the control becomes normally editable and its value accessible through text01 field.

    What is the missing ingredient in this binding receipe?