2014-11-13 6 views
6

Ich verwende diesesJavaFX nicht auf fx Anwendungsthread bei der Verwendung von Timer

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

Aber:

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

gibt mir diese Fehlermeldung:

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) 

Und ich wirklich don nicht sehen, was los ist

Antwort

27

Es kann sein, dass e Sie falsch verstanden, wie Platform.runLater() Werke ..

Das Snippet richtigen Code wäre:

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

Aber:

Ich würde Ihnen empfehlen dringend, nicht Timer zu verwenden, sondern stattdessen TimeLine! Es ist Teil der JavaFX API und Sie müssen diese Platform.runLater() Aufrufe nicht tun. Dies ist nur schnell zusammen gehackt, aber Sie bekommen die Idee:

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

Danke, es hat funktioniert! – Emrage

+0

Du hast meinen Tag gerettet :) – Klapsa2503