Node.lookupAll behaves differently before Scene is shown

John Hendrikx john.hendrikx at gmail.com
Sun Dec 25 00:05:33 UTC 2022


One thing you could try still, whether acceptable or not, is to call 
`applyCss` on the border pane before calling the count function.

As for the "and any children", I'm not sure how you should interpret 
that.  For a SplitPane, the nodes that are part of it are in the items 
list (you don't add them as actual children). The example in split pane 
also does something like `splitPane.getItems().addAll(x, y, z)`.

Same may apply to items in a List / Table / TreeView -- are they children?

--John

On 24/12/2022 19:09, Scott Palmer wrote:
> That’s interesting.  It leads me to wonder what is the expected result 
> from a call to lookupAll in various scenarios.  If, after the window 
> was showing, the SplitPane divider is pushed all the way to one size 
> such that the skin can potentially choose to leave the hidden child 
> out of the scene graph, presumable the current lookupAll 
> implementation would then fail to find it again.
>
> I think that either that’s a bug, or it needs to be made clearer in 
> the documentation that non-rendered child nodes may not be found.  I 
> personally lean toward “bug”, as I think any Node reachable through a 
> parent Node’s public API to access child nodes should be found via 
> Node.lookupAll.  I suppose you could argue that Scene.lookup is 
> searching the scene graph in a more literal sense and wouldn’t find 
> some Nodes.
>
> The docs for Scene.lookup say:
> "Looks for any node within the scene graph based on the specified CSS 
> selector.”
>
> The docs for Node.lookup say:
> "Finds this Node, or the first sub-node, based on the given CSS selector”
>
> The docs for Node.lookupAll say:
> "Finds all Nodes, including this one *and any children*, which match 
> the given CSS selector."
>
> It doesn’t mention the scene graph or if the node is currently being 
> rendered in a visible portion of the scene.  It explicitly states “any 
> children”.
>
> So I’m saying it’s a bug.
>
>
> Scott
>
>> On Dec 24, 2022, at 3:34 AM, John Hendrikx <john.hendrikx at gmail.com> 
>> wrote:
>>
>> Hi,
>>
>> In this case, this is because SplitPane doesn't actually add its 
>> split items as children -- only its Skin does this.  Skins are AFAIK 
>> installed after a CSS pass.
>>
>> In the split pane case, I guess a Skin could choose to completely 
>> leave out a child if its splitter completely hides it (ie, dragged 
>> all the way to the left or right if allowed).
>>
>> This may be another case where it may make sense to have both a 
>> document graph (logical graph) and a scene graph as Michael Strauss 
>> mentioned here: 
>> https://mail.openjdk.org/pipermail/openjfx-dev/2022-June/034417.html
>>
>> I doubt this is documented anywhere at all, it's one of those things 
>> that doesn't work quite right in JavaFX before a Scene is displayed.
>>
>> --John
>>
>> On 23/12/2022 23:49, Scott Palmer wrote:
>>> I just want to make sure this is not expected behaviour. I don’t 
>>> think so, the documentation for lookupAll doesn’t mention anything 
>>> related, but maybe I missed something somewhere else.
>>>
>>> I was just coding something to query the Scene for all SplitPanes 
>>> and save/restore the divider positions for when my application is 
>>> exiting and launching and came across this issue.
>>> My UI is fully constructed (at least in terms of all the SplitPanes 
>>> in the scene graph) before it is shown.
>>>
>>> This  code:
>>>
>>> window.getScene().getRoot().lookupAll(".split-pane")
>>>
>>> returns a different number of Nodes if I call it before showing the 
>>> window versus after showing the window.  Specifically, if I call it 
>>> before showing the window it appears to only return the first 
>>> SplitPane found in the scene graph, but calling it in an event 
>>> handler for the window shown event I get all three.
>>>
>>> This can be demonstrated with the following program:
>>>
>>>
>>> import javafx.application.Application;
>>> import javafx.scene.Scene;
>>> import javafx.scene.control.SplitPane;
>>> import javafx.scene.control.TextArea;
>>> import javafx.scene.layout.BorderPane;
>>> import javafx.stage.Stage;
>>> import javafx.stage.Window;
>>>
>>> public class LookupAll extends Application {
>>>     Window mainWindow;
>>>     public static void main(String[] args) {
>>>         launch(args);
>>>     }
>>>     @Override
>>>     public void start(Stage primaryStage) throws Exception {
>>>         var bp = new BorderPane(new SplitPane(new TextArea(),new 
>>> SplitPane(new TextArea(),new SplitPane(new TextArea()))));
>>>         var scene = new Scene(bp);
>>> primaryStage.setScene(scene);
>>>         mainWindow = primaryStage;
>>> System.out.println("Before showing:");
>>> countSplitPanes();
>>> primaryStage.setOnShown(we -> {
>>> System.out.println("After showing:");
>>> countSplitPanes();
>>>         });
>>> primaryStage.show();
>>>     }
>>>     private void countSplitPanes() {
>>>         var splitPanes = 
>>> mainWindow.getScene().getRoot().lookupAll(".split-pane");
>>> System.out.printf("Found %d SpitPanes: %s\n",splitPanes.size(), 
>>> splitPanes);
>>>     }
>>> }
>>>
>>>
>>>
>>> Before showing:
>>> Found 1 SpitPanes: [SplitPane at 16bca2d9[styleClass=split-pane]]
>>> After showing:
>>> Found 3 SpitPanes: [SplitPane at 16bca2d9[styleClass=split-pane], 
>>> SplitPane at 7078ef3c[styleClass=split-pane], 
>>> SplitPane at 56a29626[styleClass=split-pane]]
>>>
>>>
>>> Regards,
>>>
>>> Scott
>>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20221225/8f328f14/attachment-0001.htm>


More information about the openjfx-dev mailing list