JavaFXで作成したスレッド上でGUIを操作しようとするとエラーが発生します。
このエラーを回避する方法としてPlatform.runLaterを使用する方法を紹介します。
別スレッドでGUIを操作するとエラーが発生する
メインスレッドとは別のスレッドでGUIを操作する処理を行うと以下のようなエラーが発生します。
Exception in thread "Thread-5" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-5
Platform.runLater を使用する方法
Pralform.runLater関数を使用することで、別スレッドからGUI等を操作する処理を行ってもエラーが出ず正常に処理することができ、JavaFXのメインスレッド上で処理することができます。
Platform.runLater( () -> { // GUI操作処理 });
サンプルプログラム
import javafx.application.Application; import javafx.application.Platform; import javafx.concurrent.Task; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.layout.FlowPane; import javafx.scene.paint.Color; public class Main extends Application { @Override public void start(Stage primaryStage) { try { FlowPane root = new FlowPane(); Label label = new Label("テキスト変更前"); root.getChildren().add(label); // ラベルの文字を3秒後に変更するタスクを作成 Task<Boolean> task = new Task<Boolean>() { @Override protected Boolean call() throws Exception { Thread.sleep(3000); // 重い処理の代わり // Platform.runLater を使用するとメインスレッド上で処理されます。 Platform.runLater( () -> { label.setText( "テキスト変更後" ) ; }); // ↓ Platform.runLaterを使わずラベルを変更しようとするとエラーになる // label.setText( "テキスト変更後" ); return true; } }; Button btn = new Button("ボタン"); // ボタンクリックイベントを設定 btn.setOnMouseClicked(ev -> { // タスクを実行 Thread t = new Thread( task ); t.setDaemon( true ); t.start(); }); root.getChildren().add(btn); // シーンを作成 Scene scene = new Scene(root, 800, 400, Color.BLACK); scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); // ステージにシーンを登録し、ウィンドウを表示する。 primaryStage.setScene(scene); primaryStage.setTitle("JavaFX Thread からGUI操作する"); primaryStage.show(); } catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) { launch(args); } }
参考:
https://docs.oracle.com/javase/jp/8/javafx/interoperability-tutorial/concurrency.htm#JFXIP546
https://docs.oracle.com/javase/jp/8/javafx/api/javafx/application/Platform.html
コメント