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.hendr...@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@16bca2d9[styleClass=split-pane]]
>> After showing:
>> Found 3 SpitPanes: [SplitPane@16bca2d9[styleClass=split-pane], 
>> SplitPane@7078ef3c[styleClass=split-pane], 
>> SplitPane@56a29626[styleClass=split-pane]]
>> 
>> 
>> Regards,
>> 
>> Scott
>> 

Reply via email to