boycod3 boycod3 - 6 months ago 58
Java Question

Showing the Progress of a Background Task

Hi i want to show the progress of a background task.

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


And below code is the progress popup i have used in my application.

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


The problem is when i run the app , No FX app thread exception occuring..

Exception in thread "Thread-6" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-6
and pointing at void call() method inside Task thread.
Is there any solution for it..

James_D
solution Actually works for me.But i got to change the code to this.

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


After changing the code again progress not showing.just followed @james_D anwser.

Answer

You are getting the exception because you are updating the UI from a background thread. You need to update the UI from the FX Application Thread. You can do this with a call to Platform.runLater() if you need to make incremental updates during your call() method execution, or (as it seems in this case: I'm not sure exactly what the loadScreen and setScreen methods do, but I am assuming they do not change the existing scene graph) if you only need to update the UI once the task is complete, update the UI in the succeeded method of the task:

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

        @Override
        protected void succeeded() {
            super.succeeded();
            content.setContent(getValue());
            App.getInstance().hideProgressIndicator(myController);
        }

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