If what you do in your loop takes a long time and should not be executed on the JavaFX application thread, (which it probably does or you probably wouldn't have this question), then you should probably run the loop in a Task, on a different thread, updating the task's progress as the loop progresses and binding the progress bar's value to the task's progress.

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ProgressFeedback extends Application {
private static final double EPSILON = 0.0000005;
@Override
public void start(Stage stage) throws Exception {
final Task<Void> task = new Task<Void>() {
final int N_ITERATIONS = 100;
@Override
protected Void call() throws Exception {
for (int i = 0; i < N_ITERATIONS; i++) {
updateProgress(i + 1, N_ITERATIONS);
// sleep is used to simulate doing some work which takes some time....
Thread.sleep(10);
}
return null;
}
};
final ProgressBar progress = new ProgressBar();
progress.progressProperty().bind(
task.progressProperty()
);
// color the bar green when the work is complete.
progress.progressProperty().addListener(observable -> {
if (progress.getProgress() >= 1 - EPSILON) {
progress.setStyle("-fx-accent: forestgreen;");
}
});
// layout the app
final StackPane layout = new StackPane(progress);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
final Thread thread = new Thread(task, "task-thread");
thread.setDaemon(true);
thread.start();
}
public static void main(String[] args) {
launch(args);
}
}
what if the task makes call to a method that does only a single job , and do not want it to be called again and again?
Then remove the loop and invoke updateProgress through multiple calls within the job as the job progresses. The loop is only present in this sample for demonstration purposes and because this is what the original question specifically asked about.
For example lets say your job has 3 stages: fetch from database, perform calculation and accumulate results. Each stage taking an estimated 30 percent, 60 percent and 10 percent of total time respectively, then you can do something like this within the call()
body of your task:
updateProgress(0, 1.0);
Data data = db.fetchData(query);
updateProgress(0.3, 1.0);
ProcessedData processed = calculator.process(data);
updateProgress(0.9, 1.0);
Result result = accumulator.reduce(processed);
updateProgress(1.0, 1.0);