Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
781 views
in Technique[技术] by (71.8m points)

java - Javafx Not on fx application thread when using timer

I'm using this

import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;



public class Main extends Application {

public static void main(String[] args) {
    launch(args);
}

@Override
public void start(Stage primaryStage) {
    Group root = new Group();
    Scene scene = new Scene(root, 600, 400);
    primaryStage.setScene(scene);
    Circle circle = new Circle(300,200,50, Color.BLACK);
    primaryStage.setTitle("Circle");
    primaryStage.setResizable(false);
    root.getChildren().add(circle);
    moveCircle(circle, scene);
    primaryStage.show();
}
public int random(int min, int max) {
    return new Random().nextInt((max - min) + min);
}

public int random(int max) {
    return random(0, max);
}

public void moveCircle(Circle circle, Scene scene) {
    Platform.runLater(() -> {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {

            @Override
            public void run() {
                circle.setCenterX(random((int) scene.getX()));
                circle.setCenterY(random((int) scene.getY()));

            }
        }, 1000, 1000);
    });
}

But this:

public void moveCircle(Circle circle, Scene scene) {
    Platform.runLater(() -> {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {

            @Override
            public void run() {
                circle.setCenterX(random((int) scene.getX()));
                circle.setCenterY(random((int) scene.getY()));

            }
        }, 1000, 1000);
    });
}

Gives me this error:

Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
    at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:204)
    at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:364)
    at javafx.scene.Scene.addToDirtyList(Scene.java:485)
    at javafx.scene.Node.addToSceneDirtyList(Node.java:424)
    at javafx.scene.Node.impl_markDirty(Node.java:415)
    at javafx.scene.shape.Shape.impl_markDirty(Shape.java:942)
    at javafx.scene.shape.Circle$1.invalidated(Circle.java:136)
    at javafx.beans.property.DoublePropertyBase.markInvalid(DoublePropertyBase.java:112)
    at javafx.beans.property.DoublePropertyBase.set(DoublePropertyBase.java:146)
    at javafx.scene.shape.Circle.setCenterX(Circle.java:122)
    at Main$2.run(Main.java:48)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)

And i really don't see what's wrong

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It may be because you misunderstood how Platform.runLater() works..

The correct code snippet would be:

public void moveCircle(Circle circle, Scene scene) {
    Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            Platform.runLater(() -> {
                circle.setCenterX(random((int) scene.getX()));
                circle.setCenterY(random((int) scene.getY()));
            });
        }
    }, 1000, 1000);
}

But:

I would strongly recommend you to not use Timer but TimeLine instead! It is part of the JavaFX API and you do not have to do these Platform.runLater() calls. This is just quickly hacked together, but you get the idea:

public void moveCircle(Circle circle, Scene scene) {
    Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), ev -> {
        circle.setCenterX(random((int) scene.getX()));
        circle.setCenterY(random((int) scene.getY()));
    }));
    timeline.setCycleCount(Animation.INDEFINITE);
    timeline.play();
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...