Element lookup by ID has no result - javafx

With the Scene Builder 2 I created a scene with following structure:
BorderPane -> SplitPane -> AnchroPane -> SplitPane -> AnchorBane. (http://pastebin.com/7LTNh1Jv)
The AnchorPane in the second SplitPane has the ID workbench-anchor. Now I try to get a reference of this AnchorPane via:
final BorderPane rootPane = loader.load();
final Node node = rootPane.lookup("#workbench-anchor");
But node is always NULL.
Does anyone know what I am doing wrong?
Thanks a lot in advance!

Lookups won't work until CSS has been applied, which typically happens on the first frame rendering. You can try performing the lookup after showing the stage. You may also be able to force this by calling
rootPane.applyCSS();
before doing the lookup.
In general, lookups are not a very robust way of finding elements of the scene graph (imho). It's probably better to do any initialization work you need in a controller class, using #FXML injections to reference the nodes.

Related

Updating an open Scene from another Scene

I'm trying to send value from Scene A to Scene B. any Idea how to get it done? Also, without opening scene B if it already opened. Thanks
It depends on what type of value it is and if the Scene's are in different classes. But if you were sending the value of a Text object in one scene to another Text object in another scene for instance, then using something like this may help:
Text sceneAvalue = new Text("Scene A value");
Text sceneBvalue = new Text(sceneAvalue.getText());
//add sceneBValue to Scene B however you usually add components to a scene

Clone a Scene in JavaFX

Is there a way to clone a scene in JavaFX ?
I currently want to keep a reference of the previous scene but can't find a simple way of doing it (except passing in the previous scene as a parameter to every new class responsible for scene creation).
Heres what I was thinking of doing (this is a snipped of my view controller)
public void switchScene(Scene newScene){
previousScene = currentScene; // something which achieves this without aliasing
currentScene = newScene;
window.setScene(newScene);
}.
However as one can observe this leads to aliasing problems.
Any way to solve this problem ?

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.

How to obtain access to children nodes in 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.

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.

Resources