Search code examples
javafxfxml

How to set Nodes from FXML JavaFX?


I have created a Layout with FXML which consists of a BorderPane with a sideMenu and an innerBorderPane for other stuff...

But since I'm barely starting with FXML in JavaFX I just need to know how to do the next thing...

Custom.fxml (This is the main FXML layout)

<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>


<VBox fx:controller="Transcoro.Controllers.TabManager" alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="442.0" prefWidth="338.0" spacing="5.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <HBox prefHeight="59.0" prefWidth="124.0">
         <children>
            <VBox prefHeight="59.0" prefWidth="90.0" style="-fx-background-color: blue;" />
            <VBox alignment="CENTER_LEFT" prefHeight="59.0" prefWidth="165.0">
               <children>
                  <Label text="Bienvenido, Rodolfo">
                     <font>
                        <Font name="System Bold" size="15.0" />
                     </font>
                  </Label>
                  <Label text="Administrador" />
               </children>
               <opaqueInsets>
                  <Insets />
               </opaqueInsets>
               <HBox.margin>
                  <Insets />
               </HBox.margin>
               <padding>
                  <Insets left="10.0" />
               </padding>
            </VBox>
         </children>
         <VBox.margin>
            <Insets bottom="15.0" />
         </VBox.margin>
      </HBox>
      <Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Unidades" textAlignment="CENTER" textFill="#2491ff" />
      <Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Empleados" textAlignment="CENTER" textFill="#2491ff" />
      <Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Clientes" textAlignment="CENTER" textFill="#2491ff" />
      <Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Viajes" textAlignment="CENTER" textFill="#2491ff" />
   </children>
   <padding>
      <Insets top="20.0" />
   </padding>
</VBox>

sideMenu.fxml (This is the sideMenu FXML layout)

<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>


<fx:root type="javafx.scene.layout.VBox" alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="442.0" prefWidth="338.0" spacing="5.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <HBox prefHeight="59.0" prefWidth="124.0">
         <children>
            <VBox prefHeight="59.0" prefWidth="90.0" style="-fx-background-color: blue;" />
            <VBox alignment="CENTER_LEFT" prefHeight="59.0" prefWidth="165.0">
               <children>
                  <Label text="Bienvenido, Rodolfo">
                     <font>
                        <Font name="System Bold" size="15.0" />
                     </font>
                  </Label>
                  <Label text="Administrador" />
               </children>
               <opaqueInsets>
                  <Insets />
               </opaqueInsets>
               <HBox.margin>
                  <Insets />
               </HBox.margin>
               <padding>
                  <Insets left="10.0" />
               </padding>
            </VBox>
         </children>
         <VBox.margin>
            <Insets bottom="15.0" />
         </VBox.margin>
      </HBox>
      <Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Unidades" textAlignment="CENTER" textFill="#2491ff" />
      <Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Empleados" textAlignment="CENTER" textFill="#2491ff" />
      <Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Clientes" textAlignment="CENTER" textFill="#2491ff" />
      <Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Viajes" textAlignment="CENTER" textFill="#2491ff" />
   </children>
   <padding>
      <Insets top="20.0" />
   </padding>
</fx:root>

TabManager.java (This is the sideMenu JavaFX controller)

package Transcoro.Controllers;

import javafx.fxml.FXMLLoader;
import javafx.scene.layout.VBox;

import java.io.IOException;

public class TabManager extends VBox {

    public TabManager(){
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/resources/view/sideMenu.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }
}

MainLayout.java (This is the mainLayout JavaFX Controller)

package Transcoro.Core;

import Transcoro.Controllers.TabManager;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.*;

import java.io.IOException;

public class MainLayout extends BorderPane {
    @FXML
    private VBox sideMenu;

    @FXML
    private BorderPane innerContent;

    @FXML
    private HBox upperMenu;

    @FXML
    private ScrollPane contentScroll;

    @FXML
    private VBox otherPane;

    public MainLayout(){

        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/resources/view/Custom.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }

        TabManager _tabs = new TabManager();
        this.setSideMenu(_tabs);
    }

What I want to do is the following:

I have two layouts, the base which is the main Layout and sideMenu layout in another FXML

When I instantiate the mainLayout in my root that works fine, then when I want to insert the TabManager (VBox) into sideMenu (VBox from FXML) it doesn't work... I'm doing this:

    TabManager _tabs = new TabManager();
    this.setSideMenu(_tabs);

The only way I have made it work is by adding:

this.setLeft(this.sideMenu);

OR

this.setLeft(_tabs);

Which I think it shouldn't work that why, because I'm already stating that sideMenu goes on the Left BorderPane side, any idea on how should I approach this?


Solution

  • Firstly, remove fx:controller="Transcoro.Controllers.TabManager" from Custom.fxml. The controller is MainLayout, which you will set via FXMLLoader.

    Secondly, don't call fxmlLoader.setRoot(this); in MainLayout. You should instead retrieve the root node out from Custom.fxml, then add it to MainLayout, which itself is a BorderPane.

    Parent root = fxmlLoader.getRoot();
    this.setCenter(root);
    

    This will put everything from Custom.fxml as the center child of MainLayout.

    Thirdly, setLeft() is working because you are setting the TabManager instance (which is a VBox) as the left child of MainLayout. setSideMenu() (which is assumed as the setter of @FXML private VBox sideMenu does not work because sideMenu is just a reference injected into the controller. When you change this reference, it does not change the original layout.