søndag 28. oktober 2012

JavaFX 2.x - Bindings and Properties


JavaFX comes with a couple of cool features which Swing doesn't have. Instead of using literals like int, double, string etc, JavaFX comes with properties. The content in a Textfield is found in the textProperty() which happen to be a StringProperty class. You can get the string, but you can also do binding or adding listeners.

This is a nice way of reducing boiler plate code, and it gives the opportunity for creative solutions.



Swing code is very verbose. You have to make a lot of code in order to create what should have been easy. I cannot compare JavaFX verbosenes to other GUI framework, but it is better than Swing for sure.

A property like the StringProperty, is a regular class that wraps the string literal. The class has several interfaces like the Observable that gives the opportunity to add listeners.

Binding is about connecting properties with each other. Since we all love MVC ... or not, it will serve as a nice setting to show how it workes.

class Model
{
    private StringProperty text = new SimpleStringProperty("");

    public StringProperty textProperty() { 
        return text; 
    }
    public String getText() { 
        return textProperty().get(); 
    }
    public void setText(String text) { 
        textProperty().set(text); 
    }
}

Here we use a SimpleStringProperty in our model. Methods for setting and getting plain String objects, and a method for the text reference. I think this explain itself.

class View extends Pane
{
    private Model model;

    public View(Model model) {
        this.model = model;
    buildView();
}

private void buildView()
{
    VBox vbox = new VBox();

    Button button = new Button("Uppercase!!!");
    button.setMinWidth(Control.USE_PREF_SIZE);
    button.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent arg0) {
            System.out.println(model.getText());
            model.setText(model.getText().toUpperCase());
        }
    });

    TextField txf = new TextField();
    txf.textProperty().bindBidirectional(model.textProperty());

    Label label = new Label("text to uppercase");
    vbox.getChildren().addAll(label, txf, button);
    getChildren().add(vbox);
}

Here is a simple View class with a textfield and a button. I think you spot the binding which will link the textProperty of the textfield with the property in the model.

txf.textProperty().bindBidirectional(model.textProperty());

This one liner is very useful indeed. If you write stuff in the textfield, it will update the model. If you update the model, you update the view.

The code in this post can be found on github:
https://github.com/frtj/javafx_examples

There is lots of information on the net about this, so I'll stop for now.

http://docs.oracle.com/javafx/2/binding/jfxpub-binding.htm
http://blog.netopyr.com/2011/05/13/javafx-properties/
http://blog.netopyr.com/2011/07/24/upcoming-property-changes/

v1.0 - 28.okt.2012

1 kommentar:

  1. Nice explanation. But isn't the whole point of a property like this that you don't need the getter and setter? Why not use model.textProperty().get() rather than model.getText().

    (An interesting aside, seeing as how the field could be made final, maybe we could dare to do model.text.get()... ooooo, spooky!)

    With properties being POJOs, the bidirectional binding isn't very difficult to understand, unlike the situation with the black magic that is Flex.

    SvarSlett