2014-11-13 11 views
6

Sto usando questoJavaFX Non su thread dell'applicazione fx quando si utilizza il 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); 
    }); 
} 

Ma questo:

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

mi dà questo errore:

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) 

E ho davvero don vediamo cosa c'è che non va

risposta

27

Potrebbe essere E È frainteso come Platform.runLater() opere ..

Il frammento di codice corretto sarebbe:

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

Ma:

vi consiglio vivamente di non utilizzare Timer ma TimeLine invece! Fa parte dell'API JavaFX e non è necessario effettuare queste chiamate Platform.runLater(). Questo è solo rapidamente hackerato insieme, ma ti viene l'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(); 
} 
+0

Grazie ha funzionato! – Emrage

+0

Hai salvato la mia giornata :) – Klapsa2503

Problemi correlati