How to wait for user input on JavaFX application thread without using showAndWait?
Asked Answered
V

2

6

I'd like to pause the execution of a method on the JavaFX application thread and wait until the user does interaction with the UI. It's important not to freeze the UI.

Example:

Button start = ...
Button resume = ...

start.setOnAction(evt -> {
     System.out.println("starting");
     start.setDisable(true);
     System.out.println("please press resume button.");
     pause();
     System.out.println("done");
     start.setDisable(false);
});

resume.setOnAction(evt -> resume());

How should I implement the pause() and resume() methods?
The execution of the event handler should wait at pause(); call until the user presses the resume button and the resume method is called.

Volscian answered 22/9, 2017 at 16:14 Comment(1)
Is it really required to 'pause' within the method execution? Just finish the method instead of calling 'pause()' and do the rest of the work in the resume button's action handler.Adsorbate
V
8

You can do so by using Platform.enterNestedEventLoop to pause the execution of the event handler and Platform.exitNestedEventLoop (available since JavaFX 9) to resume the execution:

private final Object PAUSE_KEY = new Object();

private void pause() {
    Platform.enterNestedEventLoop(PAUSE_KEY);
}

private void resume() {
    Platform.exitNestedEventLoop(PAUSE_KEY, null);
}

Platform.enterNestedEventLoop returns when Platform.exitNestedEventLoop is called with the same parameter passed as first argument.

Volscian answered 22/9, 2017 at 16:14 Comment(4)
Is Platform.enterNestedEventLoop idempotent, or do calls accumulate? Specifically, if Platform.enterNestedEventLoop(...) is called, and then called from the nested loop with the same parameter, does the first call to Platform.exitNestedEventLoop (with the same parameter) release both blocks, or does it only release the block in the nested event loop (requiring a second call to release the original block)?Leffert
@Leffert It's not allowed to use the same key with enterNestedEventLoop more than once before the nested loop is exited. A IllegalArgumentException will be thrown if you try, see javadoc: IllegalArgumentException - if the specified key is associated with a nested event loop that has not yet returnedVolscian
And before Java9? :)Duda
@Duda It's a javafx 9 question. There are similar methods available in previous javafx versions, but they recide in the com.sun packages that are not recommended to be used.Volscian
W
0

I am currently running JFX 8 where I have the similar feature in the Toolkit class.

Toolkit.getToolkit().enterNestedEventLoop(obj);

and

Toolkit.getToolkit().exitNestedEventLoop(obj);

Have not looked at the JFX 9 source, but my bet is that the Platform methods are simply shortcuts to the same.

Workbook answered 6/4, 2018 at 11:43 Comment(1)
It's likely a shortcut, but always remember: Don't use private API for production because they have every single right to remove a private API and replace with something else, without telling anyone about the change. So at any point they can remove Toolkit.getToolkit().enterNestedEventLoop(Object) and make Platform.enterNestedEventLoop() call some other private stuff that does the same thing.Appendicle

© 2022 - 2024 — McMap. All rights reserved.