One of the most useful feature in JavaFX is its Data Binding and Triggers functions. According to the official tutorial, Data binding is the ability to create an immediate and direct relationship between tow variables, This allow two or more variables can automatically change when the other or others change. At the same time, A Replace Trigger is a block of code that is attached to a variable, which when the variable changes, the code is automatically executed. So let's begin here.
Here is an example :
var x = 0;
def y = bind x;
x=1;
println(y); //y now equals 1
x = 333;
println(y); // y now is 333;
That is a extreme sample example to show the use of 'bind' keyword, You can know in that example, y is binded to x, and its value is changed with x, that's the basic use of bind. Note that y is declared as a def because we don't want any thing change y by assigning a value to it.
An other example:
var myStreet= " No.2 Phoenix Garden"
var myCity = "Xiamen"
def address = bind Address {
street : myStreet;
city : myCity;
};
println({address.street});
myStreet = "No.33 NoWhere"
println({address.street});
In this example the result of execute is :
No.2 Phoenix Garden
No.33 NoWhere
So, the conclusion is we can bind a variable with the value of a bound expression, which can be a basic type, an object, the outcome of a function, or the outcome of an expression. But in this example we must note that the changing of myStreet actually causes a new Address object to be created and then re-assigned to the address variable. If you don't want this happen, you can change the definition like this:
def address = bind Address{
street: bind myStreet;
city : myCity;
}
By this, you can change street without create a new object, and the bind in def line can be omited.
In next step, let us look at Binding and Functions.
Here is an example :
var scale = 1.0;
bound function makePoint(xPos : Number, yPos : Nubmer) : Point {
Point {
x: xPos * scale;
y: yPos * scale;
}
}
class Point {
var x : Number;
var y : Number;
}
var myX = 5.0;
var myY = 9.0;
def pt = bind makePoint(myX, myY);
println(pt.x);
myX *=2;
println(pt.x);
scale = 2.0;
println(pt.x);
At the head of this code, we announce a bound function by 'bound' keyword, and then we use our own myX and myY number to create a Point by that bound function, note we use bind keyword before the invocation of makePoint function, so pt binded to the outcome of makePoint function.
The result of executing is :
5.0
10.0
20.0
But if we remove the bound keyword from makePoint function(it became a non-bound function), the result would be:
5.0
10.0
10.0
The different between these two situation is a bound function will get re-invoked when every variable related to the function changed while the non-bound function only do that when one of their arguments change. And we MUST NOTE that bound function and bind keyword is work together.
In next step, let us look at Binding with Sequences:
Here is an example:
var q1 = [1..10];
def q2 = bind for (item in q1) item *8;
printSeqs();
insert 11 into q1;
function printSeqs() {
println("First Sequence:");
for( i in q1) { println(i) ; }
println("Second Sequence:");
for( i in q2) { println(i) ; }
}
You can guessed the result is first sequence is 1 to 10 with step of 1 and the second sequence is 8 to 80 with step of 8.
In this example, we bind two sequence by placing the bind before the for. For more understanding, we can try to change one or some items of q1, you can find the corresponding items q2 will automatically changed and others will not be affect, like we do in the example we insert a item 11 into the end of q1 and q2 automatically generated a item 88 at the end of itself.
Finally, let us look at the Replace Triggers.
It is arbitrary blocks of code that attach to variables and execute whenever the variable's value changes. Here is an example:
var test = "test" on replace oldValue {
println(" value has changed, old value is { oldValue}");
}
test = "no";
The trigger will fires two times, first is the initialized to "test" and the next is fires When the code "test= "no"; " executed, the program will report value has changed. NOTE that the oldValue store the value of test before the trigger was invoked.