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
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With