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