Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute task in background in JavaFX

I want to load up to nine panels in a TilePane. For each pane I have to first run a computation of the content (about 300ms) and then I have to build the Panel (about 500ms).

What I want is, that there are nine ProgressIndicators which exchanges with every panel after its computation.

I tried it with the Platform.runLater command as well as with a service class. The result was always the same. The ProgressIndicator are shown, but not animated. After seconds there are all panels at once.

Is there a possibility, that the Indicators are animated the whole time and that I can exchange them one after another?

like image 944
Yggdrasil Avatar asked Feb 06 '12 18:02

Yggdrasil


People also ask

Is JavaFX multithreaded?

JavaFX provides a complete package to deal with the issues of multithreading and concurrency. There is an interface called Worker, an abstract class called Task, and ScheduledService for this purpose. The Task is basically a Worker implementation, ideal for implementing long running computation.

Is JavaFX thread safe?

The JavaFX scene graph, which represents the graphical user interface of a JavaFX application, is not thread-safe and can only be accessed and modified from the UI thread also known as the JavaFX Application thread.

What does platform runLater do?

runLater. Run the specified Runnable on the JavaFX Application Thread at some unspecified time in the future. This method, which may be called from any thread, will post the Runnable to an event queue and then return immediately to the caller. The Runnables are executed in the order they are posted.

What is JavaFX application thread?

JavaFX uses a single-threaded rendering design, meaning only a single thread can render anything on the screen, and that is the JavaFX application thread. In fact, only the JavaFX application thread is allowed to make any changes to the JavaFX Scene Graph in general.


1 Answers

JavaFX has Event Dispatch Thread which it uses for UI events. All work with UI should happen on this thread. And non-UI calculations shouldn't happen there to avoid lags in UI.

See next code:

public class Indicators extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        Pane root = new HBox();
        stage.setScene(new Scene(root, 300, 100));

        for (int i = 0; i < 10; i++) {
            final ProgressIndicator pi = new ProgressIndicator(0);
            root.getChildren().add(pi);

            // separate non-FX thread
            new Thread() {

                // runnable for that thread
                public void run() {
                    for (int i = 0; i < 20; i++) {
                        try {
                            // imitating work
                            Thread.sleep(new Random().nextInt(1000));
                        } catch (InterruptedException ex) {
                            ex.printStackTrace();
                        }
                        final double progress = i*0.05;
                        // update ProgressIndicator on FX thread
                        Platform.runLater(new Runnable() {

                            public void run() {
                                pi.setProgress(progress);
                            }
                        });
                    }
                }
            }.start();
        }

        stage.show();

    }
}
like image 74
Sergey Grinev Avatar answered Oct 23 '22 03:10

Sergey Grinev