How to get all nodes in parent in JavaFX?

In C #, I found a method that was pretty nice, which allowed you to get all descendants and all their descendants from the specified control.

I am looking for a similar method for JavaFX.

I have seen that the Parent class is what I want to work with, as it is the class from which all Node classes bearing children are derived.

This is what I have so far (and I actually haven’t found anything on google with search queries such as “JavaFX get all nodes from the scene”):

 public static ArrayList<Node> GetAllNodes(Parent root){ ArrayList<Node> Descendents = new ArrayList<>(); root.getChildrenUnmodifiable().stream().forEach(N -> { if (!Descendents.contains(N)) Descendents.add(N); if (N.getClass() == Parent.class) Descendents.addAll( GetAllNodes((Parent)N) ); }); } 

So, how can I determine if N is a parent (or extended from a parent)? Am I doing it right? It seems that it does not work ... It captures all nodes from the root (parent) of Node, but not from nodes with children in them. I feel that this is what probably got the answer, but I'm just asking the question ... wrong. How can I do it?

+9
java recursion javafx javafx-8
source share
6 answers
 public static ArrayList<Node> getAllNodes(Parent root) { ArrayList<Node> nodes = new ArrayList<Node>(); addAllDescendents(root, nodes); return nodes; } private static void addAllDescendents(Parent parent, ArrayList<Node> nodes) { for (Node node : parent.getChildrenUnmodifiable()) { nodes.add(node); if (node instanceof Parent) addAllDescendents((Parent)node, nodes); } } 
+15
source share

Unfortunately, for most components of the container, these subnodes will not receive. If you try TabPane as the parent, you will not find children, but you can find the tabs in it using getTabs() . Same thing with SplitPane and others. Therefore, a specific approach will be required for each container.

You can use node.lookupAll("*") , but it also does not look inside.

The solution may be the "Prototype" template - creating a metaclass with a common getChildren() method interface, which is implemented in subclasses - one for each type.

An example approach is presented here .

+1
source share

I use this

 public class NodeUtils { public static <T extends Pane> List<Node> paneNodes(T parent) { return paneNodes(parent, new ArrayList<Node>()); } private static <T extends Pane> List<Node> paneNodes(T parent, List<Node> nodes) { for (Node node : parent.getChildren()) { if (node instanceof Pane) { paneNodes((Pane) node, nodes); } else { nodes.add(node); } } return nodes; } } 

Using

 List<Node> nodes = NodeUtils.paneNodes(aVBoxOrAnotherContainer); 

This source code uses links from existing nodes. He does not clone them.

+1
source share

I would like to add to Hans answer that you should check if the parent is SplitPane . Since SplitPane has an empty list using getUnmodifiableChildren() , you have to use getItems() . (I do not know if there are other parents who do not provide their children through getUnmodifiableChildren() . SplitPane was the first I found ...)

0
source share

This seems to get all the nodes. (In Kotlin)

 fun getAllNodes(root: Parent): ArrayList<Node> { var nodes = ArrayList<Node>() fun recurseNodes(node: Node) { nodes.add(node) if(node is Parent) for(child in node.childrenUnmodifiable) { recurseNodes(child) } } recurseNodes(root) return nodes } 
0
source share

This works for me:

 public class FXUtil { public static final List<Node> getAllChildren(final Parent parent) { final List<Node> result = new LinkedList<>(); if (parent != null) { final List<Node> childrenLvl1 = parent.getChildrenUnmodifiable(); result.addAll(childrenLvl1); final List<Node> childrenLvl2 = childrenLvl1.stream() .filter(c -> c instanceof Parent) .map(c -> (Parent) c) .map(FXUtil::getAllChildren) .flatMap(List::stream) .collect(Collectors.toList()); result.addAll(childrenLvl2); } return result; } } 
0
source share

All Articles