現在、使用されているほとんどのウィンドウシステムはイベント駆動で動作しています。マウスのクリックやキーボードからの入力だけでなく、描画要求などもイベントとして扱われます。
イベントはキューに保持され、順々に処理されていきます。ほとんどのウィンドウシステムでは、キューにアクセスする、つまりイベントを扱うのは単一のスレッドに限定されます。
もちろん、これはウィンドウシステム上で動作するアプリケーションにも適用されます。たとえば、Swingの場合、イベントを扱うスレッドはEvent Dispatch Thread (EDT)と呼ばれています。
これはJavaFXでも同様です。JavaFXの場合、イベントを扱うスレッドはJavaFX Application Threadと呼ばれます。
このことは、描画するノードもJavaFX Application Threadからしか扱えないということを意味しています。
JavaFXアプリケーションでは、メインクラスのmainメソッドにlaunchメソッドを記述します。このlaunchメソッドがJavaFX Application Threadを起動するためのメソッドです。起動されたJavaFX Application Threadがメインクラスのオブジェクトを生成し、startメソッドをコールします。
つまり、startメソッドはJavaFX Application Threadで動作するのです。
さて、ここで問題になるのが、すべての処理をJavaFX Application Threadで行っていいかどうかです。
たとえば、ファイルの読み書きや、通信、DBとのやりとりなど、GUIの処理に比較すると時間のかかる処理があります。では試しに、どうなるか、やってみましょう。
public class LongTermTask extends Application {
@Override
public void start(Stage stage) {
BorderPane root = new BorderPane();
root.setPadding(new Insets(10.0));
root.setTop(initButton());
// イメージを回転させるアニメーション
ImageView image = new ImageView(new Image("duke.png"));
RotateTransition transition = new RotateTransition(Duration.millis(2_000), image);
transition.setToAngle(360);
transition.setInterpolator(Interpolator.LINEAR);
transition.setCycleCount(Animation.INDEFINITE);
transition.play();
root.setCenter(image);
Scene scene = new Scene(root, 300, 250);
stage.setTitle("Long Time Task Demo");
stage.setScene(scene);
stage.show();
}
private Button initButton() {
// 長い時間のかかるタスクを実行するボタン
Button button = new Button("Long Term Task");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
// 長い時間のかかる処理
longExecution();
}
});
return button;
}
// 長い時間のかかる処理
private void longExecution() {
try {
Thread.sleep(10_000);
} catch (InterruptedException ex) {}
}
public static void main(String... args) {
launch(args);
}
}
このアプリケーションはボタンと回転するイメージを表示します。ボタンをクリックすると、赤字で示した時間のかかる処理を行います。ここでは単純化するために、単にスリープを行っているだけです。