显示后台任务的进度

时间:2016-05-26 17:08:13

标签: java javafx-8

您好我想展示后台任务的进度。

@FXML
    private void addOfficeBarrierSelect() {
        App.getInstance().showProgressIndicator(myController);
        Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                ScreensController colllectScreenController = new ScreensController();
                colllectScreenController.loadScreen(Screens.ADD_OFFICE_BARRIER);
                colllectScreenController.setScreen(Screens.ADD_OFFICE_BARRIER);
                content.setContent(null);
                content.setContent(colllectScreenController);
                return null;
            }

            @Override
            protected void succeeded() {
                App.getInstance().hideProgressIndicator(myController);
            }

            @Override
            protected void failed() {
                super.failed();
                App.getInstance().hideProgressIndicator(myController);
            }
        };
        new Thread(task).start();
    }

以下代码是我在我的应用程序中使用的进度弹出窗口。

public void showProgressIndicator(ScreensController myController) {
        myController.setDisable(true);
        if (popupProgressIndicator == null) {
            JFXSpinner spinner = new JFXSpinner();
            spinner.setLayoutX(0);
            spinner.setLayoutY(0);
            spinner.setPrefHeight(200);
            spinner.setPrefWidth(200);
            popupProgressIndicator = new Popup();
            popupProgressIndicator.getContent().add(spinner);
        }
        if (!popupProgressIndicator.isShowing()) {
            popupProgressIndicator.show(primaryStage);
            popupProgressIndicator.centerOnScreen();
        }
    }
public void hideProgressIndicator(ScreensController myController) {
        myController.setDisable(false);
        if (popupProgressIndicator.isShowing())
            popupProgressIndicator.hide();
    }

问题是当我运行应用程序时,没有发生FX应用程序线程异常..

Exception in thread "Thread-6" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-6并指向Task线程内的void call()方法。 有没有解决方案..

James_D解决方案实际上对我有用。但我必须将代码更改为此。

showProgressIndicator(myController);
Task<FXMLLoader> task = new Task<FXMLLoader>() {
            @Override
            protected FXMLLoader call() throws Exception {
                FXMLLoader loader = new FXMLLoader(App.class.getResource(Screens.ADD_MEMBER));
                return loader;
            }
            @Override
            protected void succeeded() {
                super.succeeded();
                hideProgressIndicator(myController);
            }
            @Override
            protected void failed() {
                super.failed();
    hideProgressIndicator(myController);
            }
        };
new Thread(task).start();

再次更改代码后,进度不显示。只需跟随@james_D anwser。

2 个答案:

答案 0 :(得分:2)

您正在获取异常,因为您正在从后台线程更新UI。您需要从FX应用程序线程更新UI。如果您需要在Platform.runLater()方法执行期间进行增量更新,或者(在这种情况下似乎:我不确定{{1}是什么,您可以通过调用call()来执行此操作如果您只需要在任务完成后更新UI,则可以使用loadScreen方法更新UI任务:

setScreen

答案 1 :(得分:-1)

这是一个简单的例子来说明如何使用AnimationTimer和一些状态(busy和labelText)来完成它。在动画计时器的每个刻度上修改按钮和标签的状态。而任务是更新状态(不是UI)的东西。

当然,这里的状态需要同步,因此您可能希望实现一个postMessage()方法,该方法允许任务将状态报告回UI,然后将其添加到消息队列中,然后由AnimationTimer消耗。但是,下面提供的代码仅用于 ILLUSTRATIVE PURPOSES 。关键是要强调您无法从非UI线程更新UI控件

我还添加了一个ProgressBar,并将其progressProperty绑定到任务的progressProperty。因此,有两种方法可以为您管理更新:)

使用progressProperty()绑定可能是最好的。在该实例中不需要AnimationTimer。但是,如果你实现了这种方式,那么你应该在UI线程上实现一个消息队列,并通过postMessage()方法同步状态更改。

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Progress extends Application {
    String labelText = "Foobar";
    boolean busy = false;

    @Override
    public void start(Stage stage) {
        Label label = new Label();
        ProgressBar progress = new ProgressBar();
        progress.setProgress(0);
        Button button = new Button("Test");
        button.setOnAction(new EventHandler<ActionEvent>() {
            public void handle(ActionEvent event) {
                System.out.println("Button has been pressed...");
                Task<Void> task = new Task<Void>() {
                    @Override
                    protected Void call() throws Exception {
                        busy = true;
                        System.out.println("Calling long running task...");
                        for (int i = 0; i <= 100; i++) {
                            labelText = "Progress: " + i;
                            updateProgress(i, 100);
                            Thread.sleep(50);
                        }

                        return null;
                    }

                    @Override
                    protected void succeeded() {
                        System.out.println("Succeeded");
                        busy = false;
                    }

                    @Override
                    protected void failed() {
                        System.out.println("Failed");
                    }
                };

                progress.progressProperty().bind(task.progressProperty());
                Thread thread = new Thread(task);
                thread.start();
            }
        });

        AnimationTimer timer = new AnimationTimer() {
            @Override
            public void handle(long now) {
                label.setText(labelText);
                button.setDisable(busy);
            }
        };
        timer.start();

        VBox vbox = new VBox(label, progress, button);
        Scene scene = new Scene(vbox, 400, 300);
        stage.setTitle("Test");
        stage.setScene(scene);
        stage.show();
    }
}

注意,任务必须对控件无效,只有状态。

另见:https://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm

这个问题:JavaFX : How to pass value from background thread to JavaFX UI thread with Task