19

I am trying to write a code that will make things appear on the screen at predetermined but irregular intervals using javafx. I tried to use a timer (java.util, not javax.swing) but it turns out you can't change anything in the application if you are working from a separate thread.(Like a Timer) Can anyone tell me how I could get a Timer to interact with the application if they are both separate threads?

Antonio J.
  • 1,750
  • 3
  • 21
  • 33
i .
  • 485
  • 2
  • 10
  • 23
  • 1
    See [How to update a label every 2 seconds in JavaFX](http://stackoverflow.com/questions/16128423/how-to-update-the-label-box-every-2-seconds-in-java-fx/16138351#16138351); i.e use [Platform.runLater](http://docs.oracle.com/javafx/2/api/javafx/application/Platform.html#runLater(java.lang.Runnable)) to update UI from a seperate thread or use the [JavaFX animation framework](http://docs.oracle.com/javafx/2/api/javafx/animation/package-summary.html) to keep everything on the UI thread. – jewelsea May 27 '13 at 02:24

3 Answers3

22

You don't need java.util.Timer or java.util.concurrent.ScheduledExecutorService to schedule future actions on the JavaFX application thread. You can use JavaFX Timeline as a timer:

new Timeline(new KeyFrame(
        Duration.millis(2500),
        ae -> doSomething()))
    .play();

Alternatively, you can use a convenience method from ReactFX:

FxTimer.runLater(
        Duration.ofMillis(2500),
        () -> doSomething());

Note that you don't need to wrap the action in Platform.runLater, because it is already executed on the JavaFX application thread.

River
  • 8,585
  • 14
  • 54
  • 67
Tomas Mikula
  • 6,537
  • 25
  • 39
  • how do you pause and resume the ReactFX's Timer and FxTimer if using ReactFX ? I'm using it to save something periodically. Is there an equivalent pause() and play() in ReactFX, just like Timeline's pause() and play() ? – mk7 Aug 01 '16 at 19:25
19

berry120 answer works with java.util.Timer too so you can do

Timer timer = new java.util.Timer();

timer.schedule(new TimerTask() {
    public void run() {
         Platform.runLater(new Runnable() {
            public void run() {
                label.update();
                javafxcomponent.doSomething();
            }
        });
    }
}, delay, period);

I used this and it works perfectly

Flo C
  • 421
  • 4
  • 8
18

If you touch any JavaFX component you must do so from the Platform thread (which is essentially the event dispatch thread for JavaFX.) You do this easily by calling Platform.runLater(). So, for instance, it's perfectly safe to do this:

new Thread() {
    public void run() {
        //Do some stuff in another thread
        Platform.runLater(new Runnable() {
            public void run() {
                label.update();
                javafxcomponent.doSomething();
            }
        });
    }
}.start();
Michael Berry
  • 70,193
  • 21
  • 157
  • 216