May 21, 2012

“You can leverage the power of Java by using any Java library within a JavaFX application. This way you can preserve your investment in Java and use JavaFX to build engaging visual experiences.”

The statement above is in the JavaFX FAQ at 4.4. And of course you can use any java library available without any changes.

However try to bind a variable form a simple java class to any value in a javafx class and you will see that integrating java into javafx is not as simple as it seems.


The problem is with the implementation of binding in javafx. All of the built in data types in javafx are actually wrappers around java data types. You can think about them as event sources. Whenever the value changes the wrapper will notify all related variables which are bound to this variable. (If you know property change listeners you will notice the similarity).

However normal java data types are not wrapped, so if you want to use them in javafx binding you have to code a bit more.

This is a solution I posted on the javafx forum at sun:

The Thread which updates a value in every second:

// TimeServer.java
public class TimeServer extends Thread {

    private boolean interrupted = false;
    public ValueObject valueObject = new ValueObject();

    @Override
    public void run() {
        while (!interrupted) {
            try {
                valueObject.setValue(Long.toString(System.currentTimeMillis()));
                sleep(1000);
            } catch (InterruptedException ex) {
                interrupted = true;
            }
        }
    }
}

The ValueObject class which contains the values we want to bind in javafx:

// ValueObject.java
import java.util.Observable;

public class ValueObject extends Observable {

    private String value;

    public String getValue() {
        return this.value;
    }

    public void setValue(String value) {
        this.value = value;
        fireNotify();
    }

    private void fireNotify() {
        setChanged();
        notifyObservers();
    }
}

We also need an adapter class in JFX so we can use bind:

// ValueObjectAdapter.fx
import java.util.Observer;
import java.util.Observable;

public class ValueObjectAdapter extends Observer {

    public-read var value : String;
    public var valueObject : ValueObject
        on replace { valueObject.addObserver(this)}

    override function update(observable: Observable, arg: Object) {
         // We need to run every code in the JFX EDT
         // do not change if the update method can be called outside the Event Dispatch Thread!
         FX.deferAction(
             function(): Void {
                value = valueObject.getValue();
             }
         );
     }

}

And finally the main JFX code which displays the canging value:

// Main.fx
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import threadbindfx.TimeServer;

var timeServer : TimeServer;
var valueObjectAdapter : ValueObjectAdapter = new ValueObjectAdapter();
timeServer = new TimeServer();
valueObjectAdapter.valueObject = timeServer.valueObject;

timeServer.start();

Stage {
    title: "Time Application"
    width: 250
    height: 80
    scene: Scene {
        content: Text {
            font : Font {
                size : 24
            }
            x : 10, y : 30
            content: bind valueObjectAdapter.value;
        }
    }
}

I hope this helps until sun comes out with a better solution.

Comments

  1. Nice site , i have bookmarked it for later use, thanks.

  2. tabata says:

    I like your fantastic web site. Just what I was searching for! Best regards

  3. How would this be used to implement a java timer in a javafx application? Say, for example, if the user checks the box, the timer starts and goes until it reaches whatever time the user places in another box. When it reaches that time, it performs a task.

    More specifically it’s like this

    if checkbox.checked == true
    {
    timerValue = Integer.parseInt(Timervalue.text);
    count timer until it reaches timerValue then
    execute method or class
    restart timer and count again
    }
    else
    {
    timer cancelled or timer stopped
    }

    My plan is to execute an auto-update at an interval specified by the user. I have everything working, except for the timer itself. I tried a timeline, however that fails to trigger.

    Thanks for any information, and have a great day:)
    Patrick.

  4. Hi, I really appreciate all the excellent content you may have the following. I am glad I stumbled upon your web page.

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*