1

JavaFX documentation says that you could freely build node hierarchy outside of JavaFX Thread as long as none of nodes are connected to scene. If node is connected to an actual scene, than all operations should be done inside the JavaFX Application Thread.

The question: is it possible to determine if given node belongs to a scene.

And if not operations could be performed immediately in other case - with runLater method. I'd like to avoid frequent passing between threads when it is not necessary.

Node class has getScene method that returns null when the node is free. But is it thread-safe?

ayvango
  • 5,867
  • 3
  • 34
  • 73
  • 1
    I would assume that `node.getScene()` is not threadsafe, since nodes can only be added to scenes on the FX Application Thread. It's quite hard to see a use-case where there are time-consuming operations you'd want to perform on nodes and you don't already know whether they are part of a scene graph (i.e. you'd typically only do operations like this in a background thread when initializing nodes). What are you actually trying to do? Maybe there is another solution entirely. – James_D Mar 11 '16 at 23:55
  • I could determine if node is already connected from program perspective. But it requires attention to keep this requirement in mind in static. Simple wrapper that checks dynamically is easier for use. – ayvango Mar 12 '16 at 00:10

1 Answers1

2

Potential (undesirable) answer

You could invoke node.getScene() safely using Platform.runLater(), and return the result as defined in: Return result from javafx platform runlater and it would work, but I don't think I'd recommend that on a very frequent basis as it could be quite an inefficient approach for a concurrent application.

Potential alternate approach

What follows is more an alternate suggestion than an answer and there is a reasonable chance it will not fit your requirements, but is probably worth an answer for consideration.

I advise flipping your logic around. Instead of:

if given node belongs to a scene. And if not operations could be performed immediately in other case - with runLater method.

Try:

  • if you are on the JavaFX application thread perform the operation immediately, otherwise, just assume the item is attached to an active scene and perform the operation later via runLater

This is how things in other concurrent items internal to JavaFX such as tasks work. An example from the Task implementation is:

// If this method was called on the FX application thread, then we can
// just update the state directly and this will make sure that after
// the cancel method was called, the state will be set correctly
// (otherwise it would be indeterminate). However if the cancel method was
// called off the FX app thread, then we must use runLater, and the
// state flag will not be readable immediately after this call. However,
// that would be the case anyway since these properties are not thread-safe.
if (isFxApplicationThread()) {
    setState(State.CANCELLED);
} else {
    runLater(() -> setState(State.CANCELLED));
}

. . .

// This method exists for the sake of testing, so I can subclass and override
// this method in the test and not actually use Platform.isFxApplicationThread.
boolean isFxApplicationThread() {
    return Platform.isFxApplicationThread();
}
Community
  • 1
  • 1
jewelsea
  • 150,031
  • 14
  • 366
  • 406