FXML onAction Binding

There’s been some discussions around JavaFX, FXML and binding – which I stumbled across while researching a problem I’m currently having.  The examples given here demonstrate some ideas which look like they may be included in future FXML releases.

My ‘HelloWorld’ examples, which were similar (and now tailored to follow them more closely), were trying to bind the FXML onAction attributes to methods in other objects in the controller.  These objects are intended to, ultimately, be ‘Action controllers’ that are shared across different FXML controllers.  They’re intended to handle binding for enabling / disabling, images, text, hints, etc and (above all) the action handler itself.

The code below does not work.  I’d assumed it would (though the referenced site above leads me to think that was a wrong assumption).

Sample.java

package example;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;

public class Sample implements Initializable {

    @FXML
    private Label label;

    @FXML
    private TextField textField;

    @FXML
    private MyAction myAction;

    @FXML
    private MyModel myModel;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
    }
}

MyModel.java

package example;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class MyModel {
    public StringProperty myTextProperty() {
        return myTextProperty;
    }

    public String getMyText() {
        return myTextProperty.get();
    }

    public void setMyText(String text) {
        myTextProperty.set(text);
    }

    private StringProperty myTextProperty = new SimpleStringProperty("My text");
}

MyAction.java

package example;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;

public class MyAction {

    public ObjectProperty<EventHandler<ActionEvent>> onActionProperty() {
        return onActionProperty;
    }

    public EventHandler<ActionEvent> getOnAction() {
        return onActionProperty.get();
    }

    public void setOnAction(EventHandler<ActionEvent> onAction) {
        onActionProperty.set(onAction);
    }

    private EventHandler<ActionEvent> handler = new EventHandler<ActionEvent>(){
        @Override
        public void handle(ActionEvent t) {
            System.out.println("Clicked!");
        }
    };

    private ObjectProperty<EventHandler<ActionEvent>> onActionProperty = new SimpleObjectProperty<>(handler);
}

Sample.fxml

<?xml version="1.0" encoding="UTF-8"?>

<!-- <?language javascript?> -->
<?import example.MyAction?>
<?import example.MyModel?>
<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<VBox xmlns:fx="http://javafx.com/fxml"
    fx:controller="example.Sample"
    prefHeight="200"
    prefWidth="320"
    alignment="center"
    fillWidth="false">

    <fx:define>
        <MyModel fx:id="myModel" />
        <MyAction fx:id="myAction" />
    </fx:define>

    <children>
        <Label fx:id="label" text="${myModel.myText}" />
        <TextField fx:id="textField" text="${myModel.myText}" />
        <Button fx:id="button" text="Click" onAction="${myAction.onAction}" />
    </children>
</VBox>

Problems

  1. I’d expected the binding ${myModel.myText} to be bi-directional.  Referenced post states that this is currently being addressed.
  2. I’d expected the binding ${myAction.onAction} to enabled the action to be invoked.  It wasn’t.
  3. I hadn’t expected to require the <?language javascript?> PI.  It was needed to get the form to load without a “Page language not specified” error.  However it didn’t help the onAction get invoked successfully.

I’ll post further if I find a solution to the above.

Reference: FXML – Why it rocks and the next phase

Leave a Reply

Your email address will not be published. Required fields are marked *