Search code examples
servicetaskjavafx-2

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?


Solution

  • 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();
    
        }
    }