javafx
スレッディング
サーチ…
Platform.runLaterを使用したUIの更新
長期実行の操作は、JavaFXアプリケーションスレッドでは実行しないでください。これにより、JavaFXがUIを更新しなくなり、UIがフリーズすることがなくなります。
さらに、「ライブ」シーングラフの一部であるNode
への変更は、JavaFXアプリケーションスレッド上で発生する必要があります。 Platform.runLater
を使用すると、JavaFXアプリケーションスレッドでこれらの更新を実行できます。
次の例は、別のスレッドからText
Node
繰り返し更新する方法を示しています。
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class CounterApp extends Application {
private int count = 0;
private final Text text = new Text(Integer.toString(count));
private void incrementCount() {
count++;
text.setText(Integer.toString(count));
}
@Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
root.getChildren().add(text);
Scene scene = new Scene(root, 200, 200);
// longrunning operation runs on different thread
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Runnable updater = new Runnable() {
@Override
public void run() {
incrementCount();
}
};
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
// UI update is run on the Application thread
Platform.runLater(updater);
}
}
});
// don't let thread prevent JVM shutdown
thread.setDaemon(true);
thread.start();
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
UIアップデートのグループ化
以下のコードでは、ボタンクリック後、UIが応答しなくなります。これは、 Platform.runLater
呼び出しが多すぎるためです。 (ボタンをクリックした直後にListView
スクロールしてみてください。)
@Override
public void start(Stage primaryStage) {
ObservableList<Integer> data = FXCollections.observableArrayList();
ListView<Integer> listView = new ListView<>(data);
Button btn = new Button("Say 'Hello World'");
btn.setOnAction((ActionEvent event) -> {
new Thread(() -> {
for (int i = 0; i < 100000; i++) {
final int index = i;
Platform.runLater(() -> data.add(index));
}
}).start();
});
Scene scene = new Scene(new VBox(listView, btn));
primaryStage.setScene(scene);
primaryStage.show();
}
多数の更新を使用するのではなく、これを防ぐために、次のコードでは、 AnimationTimer
を使用してフレームごとに更新を1回だけ実行します。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.animation.AnimationTimer;
public class Updater {
@FunctionalInterface
public static interface UpdateTask {
public void update() throws Exception;
}
private final List<UpdateTask> updates = new ArrayList<>();
private final AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
synchronized (updates) {
for (UpdateTask r : updates) {
try {
r.update();
} catch (Exception ex) {
Logger.getLogger(Updater.class.getName()).log(Level.SEVERE, null, ex);
}
}
updates.clear();
stop();
}
}
};
public void addTask(UpdateTask... tasks) {
synchronized (updates) {
updates.addAll(Arrays.asList(tasks));
timer.start();
}
}
}
Updater
クラスを使用して更新プログラムをグループ化することができます。
private final Updater updater = new Updater();
...
// Platform.runLater(() -> data.add(index));
updater.addTask(() -> data.add(index));
JavaFX Serviceの使い方
JavaFX Thread
集中的なタスクを実行する代わりに、 Service
実行する必要があります 。基本的にサービスとは何ですか?
サービスは、新しいThread
を開始するたびに新しいThread
作成し、それにタスクを渡して何らかの作業を行うクラスです。サービスは値を返すことも、値を返すこともできません。
以下は、いくつかの作業を行い、
Map<String,String>(
)を返すJavaFX Serviceの典型的な例です。
public class WorkerService extends Service<Map<String, String>> {
/**
* Constructor
*/
public WorkerService () {
// if succeeded
setOnSucceeded(s -> {
//code if Service succeeds
});
// if failed
setOnFailed(fail -> {
//code it Service fails
});
//if cancelled
setOnCancelled(cancelled->{
//code if Service get's cancelled
});
}
/**
* This method starts the Service
*/
public void startTheService(){
if(!isRunning()){
//...
reset();
start();
}
}
@Override
protected Task<Map<String, String>> createTask() {
return new Task<Map<String, String>>() {
@Override
protected Void call() throws Exception {
//create a Map<String, String>
Map<String,String> map = new HashMap<>();
//create other variables here
try{
//some code here
//.....do your manipulation here
updateProgress(++currentProgress, totalProgress);
}
} catch (Exception ex) {
return null; //something bad happened so you have to do something instead of returning null
}
return map;
}
};
}
}
Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow