Multiple Tasks JavaFX

天大地大妈咪最大 提交于 2019-12-10 00:28:56

问题


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:


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



回答2:


I found my own solution but not sure if it's the best implementation.

Basically I just used the succeed method from Task and unbinded the progressbar and then binded it again with the new task.

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;
    }

    @Override
    protected void succeeded() {
        super.succeeded();
        updateMessage("Done");
        bar.progressProperty().unbind();
        bar.progressProperty().bind(task2.progressProperty());
        new Thread(task2).start();
    }
};

That solved the issue on how to update the progress bar for each individual task



来源:https://stackoverflow.com/questions/22971222/multiple-tasks-javafx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!