Javafx使用计时器时不在fx应用程序线程上

我正在使用这个

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); }); } 

但是这个:

 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); }); } 

给我这个错误:

 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) 

我真的没有看到什么是错的

可能是因为你误解了Platform.runLater()是如何工作的。

正确的代码段是:

 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); } 

但:

我强烈建议你不要使用Timer而是使用TimeLine ! 它是JavaFX API的一部分,您无需执行这些Platform.runLater()调用。 这很快被黑客攻击,但你明白了:

 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(); }