1

I have a time-consuming method that has to run on action of a button, and while I have that method running, I want the UI to be still active (i.e. the user can still interact with it). I have tried several solutions. One is to just run the method:

Label label = new Label("current text");
Button button = new Button("Button text");
button.setOnAction(event -> label.setText(runConputation())); // takes a long time

But that will lock the UI while it's running.

Another solution was to use a separate thread:

Label label = new Label("current text");
Button button = new Button("Button text");
button.setOnAction(event -> {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            label.setText(runConputation()); // takes a long time
        }
    });
    thread.start();
});

But this throws an IllegalStateException: not in javafx thread or something similar.

I tried adding a Platform.runLater(), as I read that will fix the Exception:

Label label = new Label("current text");
Button button = new Button("Button text");
button.setOnAction(event -> {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    label.setText(runConputation()); // takes a long time
                }
            });
        }
    });
    thread.start();
});

...but it locks the UI. It also looks ugly.

I tried to use Task as well:

Label label = new Label("current text");
Button button = new Button("Button text");
button.setOnAction(event -> {
    Thread thread = new Thread(new Task<Void>() {
        @Override
        public Void call() throws Exception {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    label.setText(runConputation()); // takes a long time
                }
            });
            return null;
        }
    });
    thread.start();
});

With similar results.

I wanted to do something like:

Label label = new Label("current text");
Button button = new Button("Button text");
button.setOnAction(event -> {
    Task<String> task = new Task<String>() {
        @Override
        public String call() throws Exception {
            return runConputation();
        }
    };
    Thread thread = new Thread(task);
    thread.start();
    // wait until thread is done
    label.setText(task.getValue());
});

Is there a way to do this?

TheCoffeeCup
  • 316
  • 5
  • 16
  • I'm not sure about JavaFX, but I believe that Swing runs on a separate thread which cannot be modified/accessed from other threads. Wouldn't FX be the same? – Ashwin Gupta Dec 06 '15 at 21:22
  • Just do `task.setOnSucceeded(e -> label.setText(task.getValue()));` (before you start the thread, obviously). – James_D Dec 06 '15 at 21:37

0 Answers0