Multiple Tasks JavaFX


Question

I've been searching for some time now on how to create multiple tasks and have them run one after the other. Here is the java code:

public class Main extends Application {

    DropShadow shadow = new DropShadow();
    Button button = new Button("Start");
    Task<Integer> task;
    Task<Integer> task2;
    Label label1 = new Label("Status: NOT STARTED");
    ProgressBar bar = new ProgressBar(0);
    ProgressIndicator pi = new ProgressIndicator(0);
    Thread th = new Thread();

    public void start(Stage stage) {
        task = new Task<Integer>() {
            protected Integer call() throws Exception {
                int iterations;
                for (iterations = 0; iterations < 1001; iterations++) {
                    if (isCancelled()) {
                        updateMessage("Cancelled");
                        break;
                    }
                    updateProgress(iterations, 1001);
                    updateMessage("Test");

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException interrupted) {
                        if (isCancelled()) {
                            //updateMessage("Cancelled");
                            break;
                        }
                    }
                }
                return iterations;
            }
        };

        task2 = new Task<Integer>() {
            protected Integer call() throws Exception {
                int iterations;
                for (iterations = 0; iterations < 1001; iterations++) {
                    if (isCancelled()) {
                        updateMessage("Cancelled");
                        break;
                    }
                    updateProgress(iterations, 1001);
                    updateMessage("Test");

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException interrupted) {
                        if (isCancelled()) {
                            //updateMessage("Cancelled");
                            break;
                        }
                    }
                }
                return iterations;
            }
        };

    task.setOnSucceeded(new EventHandler<WorkerStateEvent>(){

        public void handle(WorkerStateEvent arg0) {
            label1.setText("Done");
            new Thread(task2).start();
        }
    });

        Group root = new Group();
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.setTitle("Progress Controls");

        final Slider slider = new Slider();
        slider.setMin(0);
        slider.setMax(50);

        bar.progressProperty().bind(task.progressProperty());
        pi.progressProperty().bind(task.progressProperty());
        label1.textProperty().bind(task.messageProperty());

        button.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
            public void handle(MouseEvent e) {
                button.setEffect(shadow);
                new Thread(task).start();

            }
        });

        button.addEventHandler(MouseEvent.MOUSE_RELEASED, new EventHandler <MouseEvent>() {
            public void handle(MouseEvent arg0) {
                button.setEffect(null);
            }
        });

        final HBox hb = new HBox();
        hb.setSpacing(5);
        hb.setAlignment(Pos.CENTER);
        hb.getChildren().addAll(bar, pi, button, label1);
        scene.setRoot(hb);
        stage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}

Basically I want to have two progress bars and around 5 tasks in total. One progress bar will be for the current task running and the other one for the overall progress. Once task1 is done, I want it to run task 2 and update the progress bar back to zero while increasing the other progress one. However, once I create a new Thread for the other task nothing in the GUI gets updated.

Thanks in advance.

EDIT: I have fixed the part of the code that starts the second task. However, I have these questions:

  1. How can I create an overall progress bar that gets updated as different tasks get completed?

  2. How can I dynamically reset and update the single progress bar for each individual task once each new task is launched? Do I have to create various ProgressBar objects for this?

1
0
4/9/2014 7:05:53 PM

Your solution works. It's marginal, but I would suggest it's slightly better to have a solution where task1 doesn't know about task2. You can do this by:

  1. Using an onSucceeded handler to "rebind" the progress bar
  2. Using a single threaded executor and submitting both tasks to it

For the "overall progress", you could create a DoubleBinding that represents the total progress.

public class Main extends Application {

    DropShadow shadow = new DropShadow();
    Button button = new Button("Start");
    Task<Integer> task;
    Task<Integer> task2;
    Label label1 = new Label("Status: NOT STARTED");
    ProgressBar bar = new ProgressBar(0);
    ProgressIndicator pi = new ProgressIndicator(0);
    Thread th = new Thread();

    public void start(Stage stage) {
        task = new Task<Integer>() {
            protected Integer call() throws Exception {
                int iterations;
                for (iterations = 0; iterations < 1001; iterations++) {
                    if (isCancelled()) {
                        updateMessage("Cancelled");
                        break;
                    }
                    updateProgress(iterations, 1001);
                    updateMessage("Test");

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException interrupted) {
                        if (isCancelled()) {
                            //updateMessage("Cancelled");
                            break;
                        }
                    }
                }
                return iterations;
            }
        };

        task2 = new Task<Integer>() {
            protected Integer call() throws Exception {
                int iterations;
                for (iterations = 0; iterations < 1001; iterations++) {
                    if (isCancelled()) {
                        updateMessage("Cancelled");
                        break;
                    }
                    updateProgress(iterations, 1001);
                    updateMessage("Test");

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException interrupted) {
                        if (isCancelled()) {
                            //updateMessage("Cancelled");
                            break;
                        }
                    }
                }
                return iterations;
            }
        };

    task.setOnSucceeded(new EventHandler<WorkerStateEvent>(){

        public void handle(WorkerStateEvent arg0) {
            label1.setText("Done");
            bar.progressProperty().unbind();
            bar.progressProperty().bind(task2.progressProperty());
        }
    });

    final int numTasks = 2 ;

    DoubleBinding totalProgress = Bindings.createDoubleBinding(new Callable<Double>() {
        @Override
        public Double call() {
            return ( Math.max(0, task1.getProgress())
                   + Math.max(0, task2.getProgress()) ) / numTasks ;
        },
        task1.progressProperty(), task2.progressProperty());

   pi.progressProperty().bind(totalProgress);

        Group root = new Group();
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.setTitle("Progress Controls");

        final Slider slider = new Slider();
        slider.setMin(0);
        slider.setMax(50);

        bar.progressProperty().bind(task.progressProperty());
        //  pi.progressProperty().bind(task.progressProperty());
        label1.textProperty().bind(task.messageProperty());

        final ExecutorService exec = Executors.newSingleThreadExecutor();

        button.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
            public void handle(MouseEvent e) {
                button.setEffect(shadow);
                exec.submit(task);
                exec.submit(task2);
            }
        });

        button.addEventHandler(MouseEvent.MOUSE_RELEASED, new EventHandler <MouseEvent>() {
            public void handle(MouseEvent arg0) {
                button.setEffect(null);
            }
        });

        final HBox hb = new HBox();
        hb.setSpacing(5);
        hb.setAlignment(Pos.CENTER);
        hb.getChildren().addAll(bar, pi, button, label1);
        scene.setRoot(hb);
        stage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}
5
4/9/2014 8:11:42 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon