At this time I would like to expand the previous article about bind with a small addition about bidirectional bind (bind with inverse).
Unlike regular variable binding, bind with inverse allows not only to bind one variable to another, but also to create a bi-directional relationship between variables.
')
As in the previous post about bind, I'll start with a simple example that shows what is bind with inverse in practice.
Consider a simple example:
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.control.Slider;
var myVar: Number = 5;
Stage {
title: "Bind"
scene: Scene {
width: 250
height: 80
content: [
Vbox {
translateX: 10
translateY: 10
spacing: 5
content: [
Slider {
max: 10
value: bind myVar with inverse
}
Slider {
max: 10
value: bind myVar with inverse
}
]
}
]
}
}
At the very beginning we defined the myVar variable, around which we will “dance”. We give it some initial value (5).
In the scene, create two Slider components and bind the values of these sliders with the variable myVar using bind. But not just bind, but add the expression "with inverse".
If we run this application, we will see a window with two sliders. It is worth pulling for one slider, as the second will be pulled too.

This is due to bidirectional binding. If we drag the slider, we change the value of its value field, and the value of the variable myVar changes with the inverse bind. The value of the second slider's value field is also associated with the value of this variable, so it will also be updated after updating myVar. If you pull the other slider, the situation will repeat.
After the essence of the bidirectional binding of variables is clearer more less, let us move on to the topic of the post, namely, we will try to create a bidirectional connection of the JavaFX variable with the Java variable.
We will use the code from the previous post about bind, just complicate the task.
First, create the listener interface again (Listener.java):
public interface Listener {
void notifyChanged (int newValue);
}
After that, we will describe the Java code (I take it unchanged from the previous post) with which we will communicate (JavaPart.java):
public class JavaPart {
private int observerableValue;
public void setObserverableValue (int newValue) {
observerableValue = newValue;
Listener l = listener;
if (l! = null)
l.notifyChanged (newValue);
}
public int getObserverableValue () {
return observerableValue;
}
private Listener listener;
public void setListener (Listener l) {
listener = l;
}
}
Next, we describe an adepter, which will allow us to make the binding we need (JavaPartAdapter.fx):
public class JavaPartAdapter extends Listener {
public-init var javaPart: JavaPart;
init {
javaPart.setListener (this);
}
public var currentValue: Integer on replace oldValue {
if (currentValue! = oldValue) {
javaPart.setObserverableValue (currentValue);
}
}
public override function notifyChanged (newValue: Integer): Void {
currentValue = newValue;
}
}
Here we had to make some additions in order to allow us to make bidirectional links, namely, a trigger is used to change the value of the variable currentValue. As soon as the variable is updated, a method is invoked that updates the value of the variable in the object described in Java.
And finally, the JavaFX code of the second half, which our adapter uses to associate its variable with a variable from the JavaPart class
Main.fx:
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.control.Button;
import javafx.scene.Group;
var myVar: Integer = 5;
def adapter: JavaPartAdapter = JavaPartAdapter {
javaPart: new JavaPart ()
currentValue: bind myVar with inverse
};
Stage {
width: 200
height: 300
scene: Scene {
content: [
Button {
text: bind "Change {myVar}"
action: function () {
adapter.javaPart.setObserverableValue (77);
}
}
Button {
translateY: 25
text: bind "Change {adapter.currentValue}"
action: function () {
myVar = 999;
}
}
]
}
}
Here we define the variable myVar, after which we make a bidirectional connection between myVar and the adapter's currentValue variable.
Next, we define two buttons. The first button changes the value of a Java class variable. The second is trying to change myVar.
Compile and run:



At the first time point, the value of myVar is 5. If you click on the first button, this will cause the set method from the Java code to be called, which will call the listener, which in turn will update the currentValue value, after which, due to the bind value myVar will also be updated.
If you press the second button, the value of myVar will change. Due to the inverse bind, the currentValue value will be changed, after which the trigger on this variable will trigger, which in turn will call the set method of the Java class, so that the value of the variable in the Java class will also be updated.
Thus, a bidirectional connection between the JavaFX variable (myVar) and the Java variable (JavaPart.observerableValue) is obtained.
I hope that this small description can be useful because it writes complex logic in Java, and uses JavaFX only for UI.
Successful experiments and only good discoveries!