我創建了一個 JavaFX 應用程式,我希望它具有以下功能:
開始運行 - 每 2 秒將 appendText() 運行到 JavaFX TextArea 時,然后隨機停止所有內容并顯示 Alert.Error。
這真的很基本。我在 Stack Overflow 上搜索了一下,但找不到任何東西。如果這已經得到回答,請指出我。
為了更好地解釋我的問題,這里有一些代碼和一些截圖。
package com.example.threadstestingplatformrunlater;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.IOException;
import static java.lang.Thread.sleep;
public class HelloApplication extends Application {
private static int counter;
private TextArea textArea;
@Override public void start(Stage stage) throws IOException {
VBox vBox = new VBox();
textArea = new TextArea();
vBox.getChildren().add(textArea);
Scene scene = new Scene(vBox);
vBox.setStyle(ThemeClass.DARK_THEME);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
System.out.println("Thread Name: " Thread.currentThread().getName() );
Thread thread = new Thread(this::run);
thread.start();
}
private void functionContainingRunLater() throws InterruptedException {
System.out.println("Thread Name: " Thread.currentThread().getName() );
continuouslyWrite(textArea);
}
public static void continuouslyWrite(TextArea textArea) throws InterruptedException {
for (int i = 0; i < 20; i ) {
if(i == 10) {
Platform.runLater(()-> {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.show();
});
}
System.out.println(counter);
textArea.appendText(Thread.currentThread().getName() ": " counter "\n");
counter ;
if (counter > 500) {
break;
}
sleep(200);
}
}
public static void main(String[] args) {
launch();
}
private void run() {
try {
functionContainingRunLater();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
這段代碼運行,它正在 TextArea 上寫行。實時。到目前為止,我遇到了很多問題-或多或少,它只會在一切完成后才寫。
現在我想在 時停止它i == 10,但我只顯示 Alert.Message 然后它一直持續到結束。我想讓代碼暫停。我怎么能做到這一點?

我嘗試過:
public static void continuouslyWrite(TextArea textArea) throws InterruptedException {
for (int i = 0; i < 20; i ) {
if(i == 10) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.show();
}
System.out.println(counter);
textArea.appendText(Thread.currentThread().getName() ": " counter "\n");
counter ;
if (counter > 500) {
break;
}
sleep(200);
}
}
But in this case, I get the error of not being on JavaFX thread.
Exception in thread "Thread-3" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3
Could you help me understand how could I achieve this? Is what I want to do even possible? Somehow I can not get my head around it.
uj5u.com熱心網友回復:
正如評論中所述,以及本網站上的許多問題以及 API 檔案中的顯著位置,您不得從后臺執行緒更新 UI。不會對此TextArea進行檢查并拋出例外,但您仍然違反了 JavaFX 的執行緒規則。
僅僅因為您的代碼恰好在您的特定系統上以及您正在使用的特定 JavaFX/JVM 版本上作業并不意味著您的代碼沒有損壞。
通常,要定期運行更新 UI 的內容,您應該使用影片 API。請參閱JavaFX 定期后臺任務,特別是這個答案。在您的情況下,這有點棘手,因為您不能showAndWait()直接從影片事件處理程式呼叫。
所以你可以做這樣的事情:
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.io.IOException;
public class HelloApplication extends Application {
private int counter;
private TextArea textArea;
@Override public void start(Stage stage) throws IOException {
VBox vBox = new VBox();
textArea = new TextArea();
vBox.getChildren().add(textArea);
Scene scene = new Scene(vBox);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
System.out.println("Thread Name: " Thread.currentThread().getName() );
Timeline timeline = new Timeline();
KeyFrame keyFrame = new KeyFrame(Duration.seconds(0.2), event -> {
textArea.appendText(Thread.currentThread().getName() ": " counter "\n");
counter ;
if (counter == 10) {
timeline.pause();
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
Platform.runLater(() -> {
alert.showAndWait();
timeline.play();
});
}
});
timeline.getKeyFrames().add(keyFrame);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
public static void main(String[] args) {
launch();
}
}
如果您真的想要/需要使用執行緒(我真的不認為您這樣做),您可以使用JavaFX2 中顯示的技術:我可以暫停后臺任務/服務嗎?:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class HelloApplication extends Application {
private int counter;
private TextArea textArea;
@Override public void start(Stage stage) throws IOException {
VBox vBox = new VBox();
textArea = new TextArea();
vBox.getChildren().add(textArea);
Scene scene = new Scene(vBox);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
System.out.println("Thread Name: " Thread.currentThread().getName() );
Thread thread = new Thread(() -> {
try {
for (int i = 0; i < 20; i ) {
if(i == 10) {
FutureTask<Void> interrupt = new FutureTask<>(() -> {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.showAndWait();
return null ;
});
Platform.runLater(interrupt);
interrupt.get();
}
System.out.println(counter);
Platform.runLater(() ->
textArea.appendText(Thread.currentThread().getName() ": " counter "\n"));
counter ;
if (counter > 500) {
break;
}
Thread.sleep(200);
}
} catch (InterruptedException exc) {
Thread.currentThread().interrupt();
} catch (ExecutionException exc) {
exc.printStackTrace();
}
});
thread.start();
}
public static void main(String[] args) {
launch();
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/424572.html
