Threading and Node.lookup

Kevin Rushforth kevin.rushforth at oracle.com
Wed Mar 20 03:20:18 PDT 2013


There are some limitations in the CSS engine that require it to be 
attached to the scene before it will process nodes. I ran into this with 
snapshot, so a common workaround for apps that want to take a snapshot 
of a Node that isn't attached to a scene is to create a dummy Scene and 
attach the node in question to that Scene. See 
http://javafx-jira.kenai.com/browse/RT-22558 for example.

-- Kevin


Richard Bair wrote:
> Actually in this case the CSS engine should process immediately (it won't batch up this call, it must be synchronous) -- however it may be that there are some shared data structures being foiled by multiple threads. Not sure though, just a wild guess :-)
>
> On Mar 20, 2013, at 12:41 AM, Tom Schindl <tom.schindl at bestsolution.at> wrote:
>
>   
>> Hi,
>>
>> The problem is that the lookup system depends on the CSS-Engine (you can
>> pass any CSS-Selector!) to having processed the Node.
>>
>> My guess is that the CSS-Engine does only processes nodes when they are
>> attached to the Scene (there's no reason for it to process them if they
>> are not attached).
>>
>> Tom
>>
>> Am 20.03.13 04:47, schrieb Scott Palmer:
>>     
>>> Yes, good point.  In that case I could delay the connection to the Scene object and instead do the lookup via the root node.  But still in this case, has a rendering pass ("pulse") happened yet on such a Scene?  Since Scene objects must be constructed and modified on the FX app thread I guess it makes sense that they would do an initial layout pass on the root node?  So perhaps John is correct.  It's late and I don't have time to construct a test case now.
>>>
>>> Scott
>>>
>>>
>>> On 2013-03-19, at 10:35 PM, Kevin Rushforth <kevin.rushforth at oracle.com> wrote:
>>>
>>>       
>>>>> Node background = scene.lookup("#background");
>>>>>           
>>>> Note that this particular call references a scene, so must be done on the FX application thread. You should not touch the scene or a node that is connected to a scene on a background thread.
>>>>
>>>> -- Kevin
>>>>
>>>>
>>>>
>>>> Scott Palmer wrote:
>>>>         
>>>>> On 2013-03-19, at 8:30 PM, John Smith <John_Smith at symantec.com> wrote:
>>>>>
>>>>>           
>>>>>> "the node lookup function doesn't function (just returns null) until a rendering pass has been run on the scene"
>>>>>>
>>>>>>             
>>>>> I don't think that is exactly right.  I'm sure I used the lookup method to grab nodes from a scene graph that I made with Scene Builder *prior* to showing it.
>>>>>
>>>>> Yep… I just checked my code, this doesn't return nulls:
>>>>>
>>>>>>>>>> Parent root = FXMLLoader.load(location);
>>>>> Scene scene = new Scene(root);
>>>>> Node top = scene.lookup("#top");
>>>>> Node background = scene.lookup("#background");
>>>>>>>>>>
>>>>> The Scene clearly was just constructed and isn't showing or part of a Stage.
>>>>> The only difference is that this is called on the Platform thread. So something must be happening that needs to run on the Platform thread.
>>>>>
>>>>> You are correct about the width/height stuff that requires a layout pass to have happened before you get reasonable values.
>>>>>
>>>>> Scott
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>           
>>>>>> +1 to Philipp's question.
>>>>>>
>>>>>> It's always been the case that the node lookup function doesn't function (just returns null) until a rendering pass has been run on the scene.
>>>>>>
>>>>>> With Philipp's sample at (https://gist.github.com/phdoerfler/5201162) , if you implemented it as an Application, placed the item to be looked up in a stage, and called lookup only *after* you called stage.show on your scene, then the lookup would work (without requiring Platform.runLater) - so some side effect of showing the scene on the stage allows nodes in the scene to be looked up.
>>>>>>
>>>>>> It works the same way as trying to get the height and width of a node before it has been shown on stage - that also does not really work as you might expect because the css needs to be processed in the rendering pass to accurately determine the height and width.  I understand why height and width work the way they do, but I was never really sure why lookup doesn't just work immediately and the delayed behavior isn't documented anywhere.
>>>>>>
>>>>>> Likely there is some hidden impl_ function you could use to trigger the rendering pass, after which the lookup would work.
>>>>>>
>>>>>> - John
>>>>>>
>>>>>> -----Original Message-----
>>>>>> From: openjfx-dev-bounces at openjdk.java.net [mailto:openjfx-dev-bounces at openjdk.java.net] On Behalf Of Kevin Rushforth
>>>>>> Sent: Tuesday, March 19, 2013 4:50 PM
>>>>>> To: Philipp Dörfler
>>>>>> Cc: openjfx-dev at openjdk.java.net List
>>>>>> Subject: Re: Threading and Node.lookup
>>>>>>
>>>>>> One of the scene graph or FXML folks should be able to reply.
>>>>>>
>>>>>> -- Kevin
>>>>>>
>>>>>>
>>>>>> Philipp Dörfler wrote:
>>>>>>
>>>>>>             
>>>>>>> Ok, threading aside: Where's my mistake?
>>>>>>>
>>>>>>> https://gist.github.com/phdoerfler/5201162
>>>>>>>
>>>>>>> ~ philipp
>>>>>>>
>>>>>>> Am 20.03.2013 um 00:30 schrieb Kevin Rushforth <kevin.rushforth at oracle.com>:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>               
>>>>>>>>> As to my understanding, one only has to use Platform.runLater for accessing nodes already attached to a Scene.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>                   
>>>>>>>> In general is is legal to call accessor and mutator methods on a Node not attached to a Scene from any thread. I don't specifically know whether lookup does anything that would add additional threading restrictions.
>>>>>>>>
>>>>>>>> -- Kevin
>>>>>>>>
>>>>>>>>
>>>>>>>> Philipp Dörfler wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>                 
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> does fooNode.lookup("#bar") have to be called using Platform.runLater if fooNode is not attached to any Scene?
>>>>>>>>> As to my understanding, one only has to use Platform.runLater for accessing nodes already attached to a Scene.
>>>>>>>>>
>>>>>>>>> However, fooNode.lookup seems to fail (= return null) for nodes which are not contained directly in it, but in another node (in my case: a ScrollPane), which is then contained in fooNode. The scene graph was provided by FXMLLoader.load(...).
>>>>>>>>>
>>>>>>>>> Placing those lookups in Platform.runLater suddenly causes them to work.
>>>>>>>>>
>>>>>>>>> This feels like an arcane bug to me, but I might be missing some core concepts.
>>>>>>>>> So - did I miss something or is this a bug?
>>>>>>>>>
>>>>>>>>> Cheers,
>>>>>>>>> Philipp
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>                   
>>>>>           
>> -- 
>> B e s t S o l u t i o n . a t                        EDV Systemhaus GmbH
>> ------------------------------------------------------------------------
>> tom schindl                 geschäftsführer/CEO
>> ------------------------------------------------------------------------
>> eduard-bodem-gasse 5-7/1   A-6020 innsbruck     fax      ++43 512 935833
>> http://www.BestSolution.at                      phone    ++43 512 935834
>>     
>
>   


More information about the openjfx-dev mailing list