Asynchronous loading [message #1250661] |
Wed, 19 February 2014 08:14  |
Eclipse User |
|
|
|
Hi All!,
When a part is loaded asynchronously, the initialize method of the controller is NOT executed by the UI Thread, from our point of view this gives more disadvantages than advantages
if in the controller you have something like
@FXML
TextField myTextField;
@Override
public void initialize(URL url, ResourceBundle bundle) {
myTextField.setTooltip(new javafx.scene.control.Tooltip("This textfield requires a tooltip"));
}
That code leads to an exception
[...]
Caused by: java.lang.IllegalStateException: Not on FX application thread; currentThread = pool-4-thread-4
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:210)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:393)
[...]
We understand the advantages of loading a SceneGraph in another thread and once it is loaded it is attached to a living scene by the UI Thread. However, we don't see advantages of running the initialized method by Non-UI. That forces the user to worry about what JavaFX API calls can use in the controller and which ones not. For instance Tooltip extends PopupControl which is a living scene graph and therefore it requires UI Thread which leads to an exception when we are loading async.
The FXMLLoader.java basically does not worry about the Thread that executes the initialize:
// FXMLLoader Line 2546:
if (controller != null) {
if (controller instanceof Initializable) {
((Initializable)controller).initialize(location, resources);
} // if
so why not do it in this way? so we hand over the UI Thread to the user
if (controller != null) {
if (controller instanceof Initializable) {
Runnable runnable = new Runnable() {
public void run() {
((Initializable)controller).initialize(location, resources);
}
};
if (Platform.isFxApplicationThread()) {
runnable.run(); // execute it now
} else {
Platform.runLater(runnable);
}
}
[...]
best
Pablo
|
|
|
|
Re: Asynchronous loading [message #1250707 is a reply to message #1250661] |
Wed, 19 February 2014 09:06   |
Eclipse User |
|
|
|
.... because this is all JavaFX code you need to discuss this with the
JavaFX people but why do you think this does not make to invoke the
controller outside the UI-Thread?
I would expect a class to execute everything on the thread I'm calling
it - your code would even not block until so I'd get back an SceneGraph
which is not connected to the controller until the Runnable is run,
leading to many raise conditions.
So I don't see big chances to get something like this into the codebase.
Tom
On 19.02.14 14:14, Pablo Gomez wrote:
> Hi All!,
>
> When a part is loaded asynchronously, the initialize method of the
> controller is NOT executed by the UI Thread, from our point of view this
> gives more disadvantages than advantages
>
> if in the controller you have something like
>
>
>
> @FXML
> TextField myTextField;
>
> @Override
> public void initialize(URL url, ResourceBundle bundle) {
> myTextField.setTooltip(new javafx.scene.control.Tooltip("This
> textfield requires a tooltip"));
> }
>
>
> That code leads to an exception
>
> [...]
> Caused by: java.lang.IllegalStateException: Not on FX application
> thread; currentThread = pool-4-thread-4
> at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:210)
> at
> com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:393)
>
> [...]
>
>
> We understand the advantages of loading a SceneGraph in another thread
> and once it is loaded it is attached to a living scene by the UI Thread.
> However, we don't see advantages of running the initialized method by
> Non-UI. That forces the user to worry about what JavaFX API calls can
> use in the controller and which ones not. For instance Tooltip extends
> PopupControl which is a living scene graph and therefore it requires UI
> Thread which leads to an exception when we are loading async.
>
>
> The FXMLLoader.java basically does not worry about the Thread that
> executes the initialize:
>
> // FXMLLoader Line 2546:
> if (controller != null) {
> if (controller instanceof Initializable) {
> ((Initializable)controller).initialize(location,
> resources);
> } // if
>
>
>
> so why not do it in this way? so we hand over the UI Thread to the user
>
>
> if (controller != null) {
> if (controller instanceof Initializable) {
> Runnable runnable = new Runnable() {
> public void run() {
> ((Initializable)controller).initialize(location, resources);
> }
> };
>
> if (Platform.isFxApplicationThread()) {
> runnable.run(); // execute it now
> } else {
> Platform.runLater(runnable); } }
> [...]
>
>
>
> best
> Pablo
>
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.04360 seconds