Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to get a child node/pane from the stage? Javafx

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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();
    }
}

>Solution :

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:

Basically the View is the GUI (your .fxml files), the Model is the classes you uses (for example you could have a Student, a Professor, and some other classes you need to implement a score system), and the Controller is where you make changes to the model data and update the View consequently.

I’ll leave here a very simple example which implements the MVC pattern:

Result:

enter image description here

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:

enter image description here

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading