How to obtain access to children nodes in javafx? - javafx

I have a tree like this:
As you can see there is GridPane with 10 columns. Each of them include BorderPane wrapped into AnchorPane. Each BorderPane is composed of 2 labels and 1 radioButton. Below you can see how it look like:
I want to ask you how to get acces from code side to these elements. I know that I can use getChildren() method on GridPane but then I get only AnchorPanes from GridPane columns. I want to go deeply, and for example set text into one of the labels.
I want to add that set id in Scene Builder is not what I want cause there will be many columns and I'm going to fill it in some loop.
Could you help me with this ?
One more thing: I build the view in Scene Builder.

You you can set a css id for the nodes within your loop at creation time. You can later lookup the nodes by the id you set. A lookup will also work on a scene to find any node or matching set of nodes within the scene.
HBox parent = new HBox();
for (int i = 0; i < N_COLS, i++) {
Node childNode = createNode();
childNode.setId("child" + i);
parent.getChildren().add(childNode);
}
. . .
Node redheadedStepchild = parent.lookup("#child5");
Of course, you can always access the child the standard object accessor way too:
Node redheadedStepchild = parent.getChildren().get(5);
If the structure is nested as you have in your question, then you can do things such as:
Node redheadedGrandchild = grandparent.getChildren().get(3).getChildren().get(5);
Such searches get convoluted over large structures and probably are best avoided as your code would get more brittle. So a css based lookup or tree traversal would probably be preferred, or a direct injection of a reference via an fx:id and #FXML, which wouldn't work well in your case because you create the items in code in a loop, hence the lookup method is probably best for you.

Related

JavaFX: iterate over a set of controls belonging to a CSS class [duplicate]

I want to define a global search in my program. My program has many nodes in a scene and there are a lot of common things on different nodes that could be searched. I think of defining a class searchable and a method for searching in each node.
So when I search by a class selector I would be able to reach all the nodes to highlight them for the user.
For example if Scene or Node has a method like this:
scene.getBySelector(".searchable").filter( (p)-> (Searchable)p.search()).forEach((p) -> (Searchable)p.setHighlited());
It is certainly can be done by iterating a scene or node children recursively but it looks to me so heavy so I'd like to know if there exists such a thig:
CSSUtils.getBySelector(".searchable").filter((p) -> p.getScene() == myScene)...
Node has methods lookup(...) and lookupAll(...) which I think are what you are looking for.

Javafx: copy node by dragging it and paste the copy by dropping it to a location in Pane

Is it possible to deep copy a Label (or any other node), so that it creates a new Label object with the same property values and then put it in Dragboard?
I want to implement this functionality: drag a label an drop it at some location in Pane. A new Label object with same property values is created in Pane at the location of the drop.
As far as I know, Label does not implement the Java Cloneable interface, and so does not have any built in way to deep copy itself, nor does Node.
You could create your own class which extends Label and implements Cloneable and in that class override the clone method, and do that for every other Node you wish to deep copy as well, this is the most robust solution, but it may be more than you need.
The other option is to just create a new Label with the same properties, which could be as simple as something like
Label newLabel = new Label(oldLabel.getText(), oldLabel.getGraphic());
Note that you may have problems with that method, as it is not a true deep copy, newLabel and oldLabel now reference the same Graphic Node, which again, you may have problems adding the same Graphic Node to the scene twice. A better copy might do something like
ImageView oldGraphic = (ImageView) oldLabel.getGraphic();
Label newLabel = new Label(oldLabel.getText(), new ImageView(oldGraphic.getImage());
This still isn't a true deep copy, but there are no rules against adding the same Image to the scene as many times as you wish, so you're safe there. This sort of approach is fine for Labels, it's only two lines (it could be collapsed down to one even, but I went for more readability), but for more complex types of nodes could get really cumbersome. If it's just labels, here's an okay solution, but otherwise it would make sense to encapsulate all the needed copying into a new clone method.

JavaFx scene lookup returning null

Button btn = new Button("ohot");
btn.setId("testId");
itemSection.getChildren().add(btn);
Node nds = itemSection.lookup("‪#‎testId‬");
What is wrong with above code?? I am getting nds=null it should be btn
Lookups in conjunction with applyCSS
Lookups are based on CSS. So CSS needs to be applied to the scene for you to be able to lookup items in the scene. See the applyCSS documentation for more information. To get accurate results from your lookup, you might also want to invoke layout, as the layout operation can effect scene graph attributes.
So you could do this:
Button btn = new Button("ohot");
btn.setId("testId");
itemSection.getChildren().add(btn);
itemSection.applyCss();
itemSection.layout();
Node nds = itemSection.lookup("‪#‎testId‬");
Alternate lookup after showing a stage
Note that some operations in JavaFX, such as initially showing a Stage or waiting for a pulse to occur, will implicitly execute a CSS application, but most operations will not.
So you could also do this:
Button btn = new Button("ohot");
btn.setId("testId");
itemSection.getChildren().add(btn);
stage.setScene(new Scene(itemSection);
stage.show();
Node nds = itemSection.lookup("‪#‎testId‬");
On CSS based lookups VS explicit references
Storing and using explicit references in your code is often preferred to using lookups. Unlike a lookup, using an explicit reference is type safe and does not depend upon a CSS application. Generating explicit references can also be facilitated by using JavaFX and FXML with the #FXML annotation for type-safe reference injection. However, both lookup and explicit reference approaches have valid use cases, so it is a really just a matter of using the right approach at the right time.

getting all nodes having a styleClass in the scene graph

I want to define a global search in my program. My program has many nodes in a scene and there are a lot of common things on different nodes that could be searched. I think of defining a class searchable and a method for searching in each node.
So when I search by a class selector I would be able to reach all the nodes to highlight them for the user.
For example if Scene or Node has a method like this:
scene.getBySelector(".searchable").filter( (p)-> (Searchable)p.search()).forEach((p) -> (Searchable)p.setHighlited());
It is certainly can be done by iterating a scene or node children recursively but it looks to me so heavy so I'd like to know if there exists such a thig:
CSSUtils.getBySelector(".searchable").filter((p) -> p.getScene() == myScene)...
Node has methods lookup(...) and lookupAll(...) which I think are what you are looking for.

Flex Tree use ITreeDataDescriptor to filter nodes

I have a flex tree component that has its data bind to a ArrayCollection. I also implemented a custom ITreeDataDescriptor to filter the tree. Everything works fine except the first level nodes will not disappear (be filtered) if there is no child node under it. It does work from the second level down.
any suggestion how it can be done?
Only want to filter out the first level node when all its children node are been filtered out.
pretty much like this example, except Parent would disappear when children are gone
the source is an ArrayCollection and it's pretty much like the following
var dataSource:ArrayCollection = new ArrayCollection();
dataSource.addItem(myObject1);
dataSource.addItem(myObject2);
dataSource.addItem(myObject3);
dataSource.addItem(myObject4);
and in myObject1 ~ myObject4 there are children ArrayCollection with the same type.
This is hard to answer without any code, but here are some suggestions on a approach:
make sure you have a root node so that you can also filter out the nodes at level 1 (the children of the root node)
do a recursive check in the getChildren() method of the ITreeDataDescriptor implementation to see if all children of a node are removed/hidden

Resources