Zunächst möchte ich darauf hinweisen, dass man parallele oder rechenintensive Aufgaben nicht immer in einen eigenständigen Thread auslagern muss. JavaFX bietet seit Version 2.0 mehrere Möglichkeiten an, Aufgabe effizient auszulagern. In dem Artikel „Concurrency in JavaFX“ wird sehr anschaulich die Verwendung von den Klassen javafx.concurrent.Task und javafx.concurrent.Service erklärt. Hier ist der Link zur API der Task-Klasse.
Zurück zum Thema: In diesem Beitrag erkläre ich, wie man seine JavaFX UI von einem beliebigen Thread aus updaten kann. Hierzu nutze ich die vom Framework bereitgestellte Funktion „Platform.runLater()„.
Um die Verwendung der Funktion besser erklären zu können, habe ich eine kleine Beispiel-Anwendung programmiert.
Das Programm zeigt dynamisch aktuelle Statusmeldungen in einer ListView an. Der folgende Screenshot zeigt die UI:
Die gesamte UI auf einmal upzudaten ist in einem externen Thread leider nicht möglich. Teilweise aktualisieren sich Komponenten selbst, jedoch kann man mit folgenden Zeilen jede Komponenten-Referenz aktualisieren:
Platform.runLater(new Runnable() { @Override public void run() { // entsprechende UI Komponente updaten } });
Da ich in meinem Beispiel nur die ListView updaten will, sieht die Thread-Klasse etwas leer aus.
package de.axxg; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import javafx.application.Platform; import javafx.scene.control.ListView; /** * * @author AxxG * @see http://blog.axxg.de/ */ public class WorkerThread extends Thread{ private ListView<String> list = null; public WorkerThread(ListView<String> list, int count) { setDaemon(true); setName("Thread " + count); this.list = list; } @Override public void run() { while (!this.isInterrupted()) { // UI updaten Platform.runLater(new Runnable() { @Override public void run() { // entsprechende UI Komponente updaten list.getItems().add(0, getName() + " sagt Hallo!"); } }); // Thread schlafen try { // fuer 3 Sekunden sleep(TimeUnit.SECONDS.toMillis(3)); } catch (InterruptedException ex) { Logger.getLogger(WorkerThread.class.getName()).log(Level.SEVERE, null, ex); } } } }
Um jetzt noch das Rätsel zu lüft, wo ich die Komponenten-Referenz her habe, kommt hier die Main-Klasse:
package de.axxg; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ListView; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.stage.Stage; /** * * @author AxxG * @see http://blog.axxg.de/ */ public class UIThreadUpdate extends Application { private ListView<String> list; private int count = 0; @Override public void start(Stage primaryStage) { // Java 7 Style;-) list = new ListView<>(); list.setPrefWidth(200); // Button erstellen Button btn = new Button(); btn.setText("Starte einen Thread"); btn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { WorkerThread myThread = new WorkerThread(list, count); myThread.start(); count++; } }); // Layout der Anwendung VBox myBox = new VBox(); // Komponenten dem Layout hinzufuegen myBox.setAlignment(Pos.CENTER); myBox.getChildren().add(btn); myBox.getChildren().add(list); // alles zusammensetzen StackPane root = new StackPane(); root.getChildren().add(myBox); Scene scene = new Scene(root, 300, 250); // Stage konfiguieren primaryStage.setTitle("AxxG - UI Thread Update"); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
Copyright © 2012 AxxG – Alexander Gräsel
Danke, Alexander! Ich habe gerade nach langem Nachdenken und Suchen den Fehler in meiner Anwendung und die Bedeutung von Platform.runLater verstanden. Schöner Artikel!
Du glaubst gar nicht wie sehr mir dein Code Schnipsel grad geholfen hat -.-! Vielen Dank fürs online stellen! Ansonsten säße ich jetzt wohl noch den ganzen Tag dran den Mist zu recherchieren. ~ ein nicht mehr ganz so frustrierter Informatik Student aus der Stadt die es nicht gibt.
Geiler Kommentar:D
Schön, dass ich dir helfen konnte!
Thanks a lot, this made my day. Your article was much more clear to me than the official ones on the Oracle website or those from Stackoverflow.
Absolutely. This helped me after running crazy for 16 hrs of searching via the web. Thanks.
Ich war seit 2 Stunden am recherchieren… UND ENDLICH HAB ICH MEINE LÖSUNG. Danke vielmals 🙂
Bitte Bitte^^