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 <[email protected]>
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