Update UI components before process finishes?

I am trying to get a spinner to work so that it shows when a table row is clicked until some process is finished.

But as a simpler example…

Even with a button:

   @Subscribe("testButton")
public void onTestButtonClick(Button.ClickEvent event) {
    notifications.create().withCaption("HELLO").show();
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

Is there any way to get the notification to show before the thread sleeps? It only shows after the Thread.sleep has completed.

Hello @daryn

I suggest you to use BackgroundWorker API. You can find usage example also in our documentation: ProgressBar with Background Task Mechanism.

I’ve prepared small example for you. For example, screen layout:

<layout spacing="true" expand="spacer">
    <button id="toggle"
            caption="Show Spinner"/>
    <label id="spinner"
           visible="false"
           stylename="spinner"/>
    <label id="spacer"/>
</layout>

In screen controller:

@Inject
private Label<String> spinner;

@Inject
private BackgroundWorker backgroundWorker;

@Subscribe("toggle")
public void onToggleClick(Button.ClickEvent event) {
    // show spinner
    spinner.setVisible(true);
    // launch task that will hide spinner later
    backgroundWorker.handle(createTimeoutTask())
            .execute();
}

private BackgroundTask<Void, Integer> createTimeoutTask() {
    return new BackgroundTask<Void, Integer>(5, TimeUnit.SECONDS) {
        @Override
        public Integer run(TaskLifeCycle<Void> taskLifeCycle) throws Exception {
            // wait 5 seconds
            Thread.sleep(5000);
            return 0;
        }

        @Override
        public void done(Integer result) {
            // hide spinner when done
            spinner.setVisible(false);
        }
    };
}

spinner-sample.zip (70.0 KB)

Regards,
Daniil

1 Like

Awesome, thanks for that.

I had tried using the background task but where I was going wrong was trying to update the Datacontainer within the task’s run method. The simple solution was to add another holder for the data list
e.g.
private List<MyEntity> myEntities

and update that list (instead of the DataContainer) within the background task and when the task was “done” to then set the DataContainer to the private List

 @Override
            public void done(Integer result) {
                myEntityDc.setItems(myEntities);
                spinnerBox.setVisible(false);

On another note…
Do you know how to make the spinner bigger?
I presume I need to create a style for it somehow?

Yes, you can do it via CSS