Javafx使用计时器时不在fx应用程序线程上 [英] Javafx Not on fx application thread when using timer

查看:1753
本文介绍了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;



公共类Main扩展Application {

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

@Override
public void start(Stage primaryStage){
Group root = new Group();
场景场景=新场景(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);
});
}

给我这个错误:

 线程Timer-0中的异常java.lang.IllegalStateException:不在FX应用程序线程上; currentThread =在com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:204)上的定时器-0 
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(圆圈,场景场景) {
定时器计时器=新的计时器();
timer.scheduleAtFixedRate(new TimerTask(){
@Override
public void run(){
Platform.runLater(() - > {
circle.setCenterX (random((int)scene.getX()));
circle.setCenterY(random((int)scene.getY()));
});
}
},1000,1000);
}

但是:



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

  public void moveCircle(圆圈,场景场景){
时间轴时间轴=新时间轴(新KeyFrame(Duration.seconds(1),ev - > {
circle.setCenterX(random((int)scene.getX()));
circle。 setCenterY(random((int)scene.getY()));
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}


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

这篇关于Javafx使用计时器时不在fx应用程序线程上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆