[英]JavaFX Task ending and JavaFX threading
我今天才剛剛開始學習JavaFX,我試圖通過制作Snake克隆來了解更多有關JavaFX的信息,但是我在線程方面遇到了麻煩。 我想創建一個線程來更新蛇在屏幕上的位置,但是無法以正常的Runnable線程方式使用它,因為我正在該線程內使用JavaFX來更新繪制到屏幕上的矩形的位置(這是我了解到的您不能做,而必須使用Tasks,Services,Platform.runLater等?)我從中創建線程的類擴展了JavaFX.scene.layout.Pane,而我正在嘗試使用任務來更新蛇的位置。 我的問題是:該任務似乎只運行了一次或兩次並退出,而我沒有給出任何中斷。
擴展Pane的類的構造函數(Snake類擴展Group):
public GameFrame(){
this.setPrefSize(800, 600);
Snake snake = new Snake();
this.getChildren().add(snake);
taskThread = new Thread(new Task<Void>() {
protected Void call() throws Exception {
while(!Thread.currentThread().isInterrupted()){
snake.updatePosition();
try{
Thread.sleep(1000);
} catch(InterruptedException e){
break;
}
}
return null;
}
});
taskThread.start();
}
我覺得我實際上並不掌握在這里要做的最好的事情,而我試圖做的事情可能有些破舊。 關於我應該做什么或如何解決這個問題,有什么建議嗎?
JavaFX中線程化的基本規則(如果您已經了解其中的一些內容,請問完整,請原諒我):
Node
的狀態的操作都應在FX Application線程上執行 為了幫助實現這些目的,JavaFX API提供了一個Task
類。 它具有一個返回值的call()
方法; 它是一個Runnable
因此可以作為Thread
構造函數的參數提供,也可以傳遞給Executor
。 它還提供了保證在FX Application Thread上執行的有用回調,例如setOnSucceeded
, setOnFailed
和各種update...()
方法,這些屬性用於更新FX Application Thread上的progress
和message
等屬性。
但是, Task
類實際上是為一次性任務而設計的:例如,考慮需要從數據庫檢索數據的應用程序,這可能會花費一些時間。 它們執行特定的操作並返回結果。 您的情況有所不同,因為您的線程正在連續執行。
在這種情況下,最好使用簡單的Thread
並使用Platform.runLater(...)
更新UI。 Platform.runLater(...)
接受一個Runnable
並在FX Application Thread上執行其run()
方法。
我不清楚您的代碼為什么會如此描述,但是假設方法調用snake.updatePosition()
導致UI發生更改,應在FX Application Thread上執行。 無論如何我都會嘗試
taskThread = new Thread(new Runnable() {
public void run() {
while(!Thread.currentThread().isInterrupted()){
Platform.runLater(new Runnable() {
@Override
public void run() {
snake.updatePosition();
}
});
try{
Thread.sleep(1000);
} catch(InterruptedException e){
break;
}
}
}
});
如果您使用的是Java 8,則用lambda替換匿名內部類會更好一些:
taskThread = new Thread( () -> {
while (! Thread.currentThread().isInterrupted()) {
Platform.runLater( snake::updatePosition );
try {
Thread.sleep(1000);
} catch (InterruptedException exc) {
break ;
}
}
});
JavaFX中用於定期執行某些操作的另一種技術是(ab?)使用Animation:
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1),
new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
snake.updatePosition();
}
}
));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
或者,在Java 8中,略顯光滑
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1),
event -> snake.updatePosition()));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.