【问题标题】:Multiple Tasks JavaFX多任务 JavaFX
【发布时间】:2014-05-23 04:00:40
【问题描述】:

我一直在寻找有关如何创建多个任务并让它们一个接一个运行的问题。这是java代码:

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

基本上我想要两个进度条和大约 5 个任务。一个进度条用于当前正在运行的任务,另一个用于总体进度。一旦 task1 完成,我希望它运行 task 2 并将进度条更新回零,同时增加另一个进度条。但是,一旦我为其他任务创建了一个新线程,GUI 中的任何内容都不会更新。

提前致谢。

编辑: 我已经修复了启动第二个任务的代码部分。但是,我有这些问题:

  1. 如何创建一个随着不同任务的完成而更新的整体进度条?

  2. 如何在每个新任务启动后动态重置和更新每个单独任务的单个进度条?我是否必须为此创建各种 ProgressBar 对象?

【问题讨论】:

  • 您的 EventHandler 为 task2 创建了一个新线程,但它从不启动线程或在任何地方存储对它的引用。
  • 刚刚解决了这个问题。但是如何重置进度条以显示任务 2 的状态?
  • @jameslarge - 我猜我必须修改 bar.progressProperty().bind(task.progressProperty());但是一旦“任务”完成并且现在“任务2”正在运​​行,我该如何动态更改?
  • @jewelsea - 可能,但我刚刚找到了解决方案

标签: java multithreading javafx task


【解决方案1】:

您的解决方案有效。这是微不足道的,但我建议最好有一个 task1 不知道 task2 的解决方案。你可以这样做:

  1. 使用 onSucceeded 处理程序“重新绑定”进度条
  2. 使用单线程执行器并向其提交两个任务

对于“总体进度”,您可以创建一个表示总进度的 DoubleBinding。

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

【讨论】:

  • 没什么大不了的:请注意我将相同的两行(bar.progressProperty().unbind();bar.progressProperty().bind(...);)放在不属于 task1 对象的 EventHandler 中。您将这些作为 task1 对象的 succeeded(...) 方法的一部分。如果您想重构它,使 task1 成为内部类或顶级类,而不是匿名类,那么按照我的做法,您不必将 task2 的引用传递给该类。 (换句话说,task2 不是 task1 实现的一部分。)
【解决方案2】:

我找到了自己的解决方案,但不确定它是否是最佳实现。

基本上我只是使用Task 中的succeed 方法并取消绑定进度条,然后再次将其与新任务绑定。

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

这解决了如何更新每个任务的进度条的问题

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    相关资源
    最近更新 更多