I've recently encountered problem, where I needed to get specific node (preferably by id) from nodes used in my window. Im using FXMLLoader, so first idea was to search tree structure FXMLLoader returns.
root|
|
|--some_container |- child1
| |- child2
|
|--other_container |-child3
...
Further research got me to method lookup in Scene class, but official documentation (https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Scene.html#lookup-java.lang.String-) is a lacking description how this method works and is inaccurate in my opinion (I struggled quite a bit to make things work).
As mentioned here (How to find an element with an ID in JavaFX?) invocation of method lookup must be after method show, why?
Second question is why node id has to be preceded by '#' (hash sign)? while official documentation states it should be "...CSS selector..."? (Im a bit confused here, because class Node contains only one id-like property)
Edi1 - simple example for @kleopatra although problem isn't strictly code, its about understanding.
Example fxml file with scene contents:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.canvas.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="display.windows.ConsoleForBoard">
<children>
<SplitPane fx:id="mainSplitPane" dividerPositions="0.7" layoutX="277.0" layoutY="100.0" prefHeight="160.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="398.0" prefWidth="404.0">
<children>
<SplitPane dividerPositions="0.8" layoutX="150.0" layoutY="53.0" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<Canvas fx:id="drawBoard" height="313.0" layoutX="125.0" layoutY="43.0" width="413.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<TextArea layoutX="107.0" layoutY="-86.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ToggleButton layoutX="35.0" layoutY="62.0" mnemonicParsing="false" text="ToggleButton" />
<TextField alignment="CENTER" layoutX="2.0" layoutY="14.0" promptText="Main Menu" text="Main Menu" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
Note: Canvas has fx:id="drawBoard"
example class that creates this scene:
public class BoardWithMenu extends Application {
Scene mainScene;
AnchorPane root;
FXMLLoader loader;
public static void start() {launch("start");}
@Override
public void start(Stage stage) throws Exception {
loader = new FXMLLoader(this.getClass().getResource("scene_definition.fxml"));
root = loader.load();
mainScene = new Scene(root, 500, 500);
stage.setScene(mainScene);
stage.setTitle("Space map");
stage.show();
Canvas board = (Canvas) mainScene.lookup("drawBoard");
System.out.println(board.getId());
}
}
Problem:
Line
Canvas board = (Canvas) mainScene.lookup("#drawBoard");
Cannot be invoked before
stage.show();
It will produce null pointer error. Why?