I need to get to my stackpane that is nested inside a borberpane which is also nested in another borderpane(root).
I did not create this by code, I used scene-builder/FXML.
I am now trying to access it through code. The closes I got was by using a parent and got a unmodifiable list which seems to only have its two child but I cant seem to go deeper.
Here is the Hierarchy---
<BorderPane fx:id="rootPane" focusTraversable="true" minHeight="0.0" minWidth="0.0" prefHeight="771.0" prefWidth="1100.0" stylesheets="@styling.css" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.passwordmanager2.HelloController">
<center>
<BorderPane fx:id="borderPane2" BorderPane.alignment="CENTER">
<top>
<StackPane fx:id="topBar" alignment="TOP_CENTER" focusTraversable="true" prefHeight="95.0" BorderPane.alignment="CENTER">
<children>
.....
Here is main method
public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
double width = 900.0;
double height = 950.0;
Scene scene = new Scene(fxmlLoader.load(), width, height);
Parent root = fxmlLoader.getRoot();
System.out.println(root.getChildrenUnmodifiable().get(3)); // trying to get stackPane
stage.setScene(scene);
stage.initStyle(StageStyle.UNDECORATED);
ResizeHelper.addResizeListener(stage);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
CodePudding user response:
You have to create fields named the same way you specified in the .fxml file (with fx:id="..."
), for each component and use the @FXML
annotation.
For example you have to add @FXML private BorderPane borderPane2;
to access the border pane object.
The best way to implement that is using the MVC design pattern. References:
-
Project structure:
src | - application (package) | -- Controller.java | -- Main.java | -- Test.fxml | -- application.css
Main.java class:
package application; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.layout.AnchorPane; import javafx.stage.Stage; public class Main extends Application { @Override public void start(Stage stage) { try { FXMLLoader loader = new FXMLLoader(Main.class.getResource("Test.fxml")); AnchorPane basePane = (AnchorPane) loader.load(); Scene scene = new Scene(basePane); scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); stage.setTitle("Test"); stage.setScene(scene); stage.show(); } catch(Exception e) { e.printStackTrace(); } } public static void main(String args[]) { launch(args); } }
Controller.java class:
package application; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Slider; import javafx.scene.control.TextField; import javafx.scene.control.Button; import javafx.scene.layout.AnchorPane; public class Controller { @FXML private AnchorPane base; @FXML private Slider sliderTest; @FXML private TextField textFieldTest; @FXML private Button buttonTest; private int counter = 0; public void initialize() { textFieldTest.setText("" counter); } @FXML private void test(ActionEvent event) { counter ; this.textFieldTest.setText("" counter); } }
Test.fxml file:
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.Button?> <?import javafx.scene.control.Slider?> <?import javafx.scene.control.TextField?> <?import javafx.scene.layout.AnchorPane?> <AnchorPane id="base" fx:id="base" prefHeight="400.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller"> <children> <TextField fx:id="textFieldTest" layoutX="125.0" layoutY="187.0" /> <Button fx:id="buttonTest" layoutX="174.0" layoutY="273.0" mnemonicParsing="false" onAction="#test" text="Increment" /> <Slider fx:id="sliderTest" layoutX="14.0" layoutY="33.0" /> </children> </AnchorPane>
application.css file:
.slider { -fx-base: red; } .button { -fx-base: blue; }
Another way to access a component (for example if it doesn't have a fx:id), you could start from the parent and, knowing the child node index, or iterating through them, you could get the interested node and cast it.
Example:Node n = base.getChildren().get(0); TextField tf = (TextField) n; System.out.println(tf); tf.setText("Hello JavaFX");
Output:
TextField[id=textFieldTest, styleClass=text-input text-field]
here the TextField is the 1st child of AnchorPane: