Reputation: 29101
Background
I have a Swing application. I run JavaFx embedded inside the swing application. I run a web browser (webview) inside the JavaFx application. I add a handler to receive the web browser's confirm
function. This handler is invoked in the JavaFx event thread. The handler is synchronous and returns a boolean
back to the webview.
Problem
To open a Swing dialog to the user, I need to run on the Swing event thread, but only return from the JavaFx callback after the dialog is responded to.
Here is an example of my callback
engine.setConfirmHandler(()->{
// in JavaFX context
CountdownLatch latch = new CountdownLatch(1);
SwingUtilities.invokeLater(()->{
// in Swing context
showModalDialog();
latch.countDown();
});
// Wait for latch
// HOW DO I BLOCK HERE AND STILL PROCESS EVENTS IN JAVAFX/SWING?
return result;
});
Question
How can I delay returning from the callback, until the dialog closes, while not blocking UI events in either the JavaFX or Swing contexts?
Upvotes: 1
Views: 501
Reputation: 29101
JavaFX has a way of blocking while still processing events.
Java 8
Toolkit.getToolkit().enterNestedEventLoop(key)
Java 9
Platform.enterNestedEventLoop(key)
Another thread can then exitNestedEventLoop
to unblock, and as a bonus, can also return a value.
Java 8
Toolkit.getToolkit().exitNestedEventLoop(key, result)
Java 9
Platform.exitNestedEventLoop(key, result)
However, when calling exitNestedEventLoop
from Swing, you must switch back to the JavaFX context.
So here's the working example (Java 8).
engine.setConfirmHandler(()->{
// in JavaFX context
SwingUtilities.invokeLater(()->{
// in Swing context
boolean result = showModalDialog();
Platform.runLater(()->{
// back to JavaFX context
Toolkit.getToolkit().exitNestedEventLoop(key, result)
})
});
// Wait for result
boolean result = Toolkit.getToolkit().enterNestedEventLoop(this)
// still in JavaFX context
return result;
});
Upvotes: 2