Search code examples
javafxprogress-indicator

Showing progress while chart is loading javafx


I'm writing a program in javafx where different charts are being shown. The chart values are based on data collected from a database. Since I have to first collect the data from the database and then do som further calculations in the code some of the charts take some time to load. I would like a progress indicator to show the progress of the chart loading. Before the chart is shown the user selects what kind of chart he/she wants and then clicks a 'Go' button to view the chart. Before the button is clicked the progress indicator looks like this and works perfectly fine:

Progress indicator

When the user clicks the 'Go' button the chart starts loading and I would like the progress indicator to show the loading progress in percent. The problem is that as soon as the chart starts loading the progress indicator freezes. All changes that I try to do to the progress bar (and the text below it) will not be done until the entire chart is fully loaded, which kind of ruins the whole purpose of the progress indicator.

Is there any way to make the progress indicator change WHILE the chart is loading?

Thanks!


Solution

  • Do this in a different Thread from a Task, update the progress and bind the progress property to the progress of the Task:

    @Override
    public void start(Stage primaryStage) {
        ProgressIndicator progressIndicator = new ProgressIndicator();
        Button btn = new Button("Go");
        VBox root = new VBox(10, btn, progressIndicator);
    
        btn.setOnAction((ActionEvent event) -> {
            Task<LineChart> task = new Task<LineChart>() {
    
                @Override
                protected LineChart call() throws Exception {
                    for (int i = 0; i < 10; i++) {
                        try {
                            // do some work
                            Thread.sleep(500);
                        } catch (InterruptedException ex) {
                        }
                        updateProgress(10 * i, 100);
                    }
                    updateProgress(100, 100);
    
                    return new LineChart(new NumberAxis(), new NumberAxis());
                }
    
            };
            progressIndicator.progressProperty().bind(task.progressProperty());
            task.setOnSucceeded(evt -> {
                // handle successful completion of task on application thread
                root.getChildren().set(root.getChildren().indexOf(progressIndicator), task.getValue());
            });
            new Thread(task).start();
        });
    
        Scene scene = new Scene(root, 300, 300);
    
        primaryStage.setScene(scene);
        primaryStage.show();
    }