2014-11-13 22 views
6

Używam tegoJavaFX Nie na wątku aplikacji fx przy użyciu timera

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

Ale:

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

daje mi ten błąd:

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) 

A ja naprawdę don nie widzę, co jest nie tak

Odpowiedz

27

To może być è niezrozumiany jak Platform.runLater() prace ..

Prawidłowy fragment kodu będzie:

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

ALE:

Zdecydowanie zalecamy, aby nie używać Timer ale TimeLine zamiast! Jest to część JavaFX API i nie musisz wykonywać tych połączeń Platform.runLater(). To jest po prostu szybko zhakowane razem, ale masz pomysł:

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

Dzięki temu zadziałało! – Emrage

+0

Uratowałeś mój dzień :) – Klapsa2503