Benoit Goderre Benoit Goderre - 17 days ago 10
Java Question

JavaFX - Indeterminate progress bar not moving even with Task

I am doing a simple UI using JavaFX. I created an application that processes SQL queries and Excel files, then displays a progress bar window while it is being executed. I have read many other stackoverflow questions that recommend the use of taks. However, even when using a JavaFX task, my progress bar is displayed, but remains empty. Here is my code:

public class ProgressBarWindow extends VBox
{
public ProgressBarWindow(Stage stage)
{
final ProgressBar pb = new ProgressBar();
pb.setProgress(ProgressBar.INDETERMINATE_PROGRESS);

Label label = new Label("Le fichier de classement est en cours de création.");

setStyle(
"-fx-padding:10; -fx-background-color: honeydew; -fx-border-color: derive(honeydew, -30%); -fx-border-width: 3;");

setPadding(new Insets(20, 20, 20, 20));
setAlignment(Pos.BASELINE_CENTER);
setSpacing(25);

getChildren().addAll(label);
getChildren().addAll(pb);
}
}

// Called when the user clicks the Finish button in a wizard
public void finish()
{
Task task = new Task<Void>()
{
@Override
public Void call()
{
try
{
StandingsCreationHelper.createStandingsFile();
}
catch (Exception ex)
{
Alert alertStandingsFileExecution = Dialog.getExceptionDialog(ex);
alertStandingsFileExecution.showAndWait();
}
return null;
}
};

new Thread(task).start();

Scene scene = new Scene(new ProgressBarWindow(owner));
owner.setScene(scene);
owner.show();

do
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
// recommended because catching InterruptedException clears interrupt flag
Thread.currentThread().interrupt();
return;
}
}
while (StandingsCreationHelper.isFinished() == false);

owner.close();
}


Thanks in advance for any help!

Note: When running the ProgressBarWindow by itself (adding a stage and a scene and showing it manually), the progress bar displays the back and forth movement that I wish to see.

Answer

You are blocking the FX Application thread, preventing it from rendering. Never do this.

You should use the task's onSucceeded handler to execute code when the task completes, and the onFailed handler to manage exceptions. Both are executed on the FX Application Thread, which allows you to interact with the UI from them.

public void finish() {

    Task task = new Task<Void>() {

        @Override
        public Void call() throws Exception {
            StandingsCreationHelper.createStandingsFile();
            return null;
        }
    };

    task.setOnFailed(e -> {
        Throwable ex = task.getException();
        Alert alertStandingsFileExecution = Dialog.getExceptionDialog(ex);
        alertStandingsFileExecution.showAndWait();
    });

    task.setOnSucceeded(e -> owner.close());

    Scene scene = new Scene(new ProgressBarWindow(owner));
    owner.setScene(scene);
    owner.show();

    new Thread(task).start();

}
Comments