Nexmo16
Nexmo16

Reputation: 137

Why are VBox children not displaying when added dynamically?

Could anyone please explain why this is not working?

Loop (should) create a repeating pattern of VBox's inside a VBox, inside a ScrollPane, inside a BorderPane (central position), each with different data drawn from a database.

    public void equipmentPaneBuilder(LinkedList<ModelEquipment> list) {
        LinkedList<ModelEquipment> equipmentList = list;

        for (int i = 0; i < equipmentList.size(); i++) {
            ModelEquipment item = equipmentList.get(i);

            try {
                PaneEquipment equipmentPane = new PaneEquipment();
                equipmentPane.updateFields(item.getTechId(), item.getShortName(), item.getLongDesc()); equipmentPane.setId("equipPane" + i);

                EquipmentPanels.getChildren().add(equipmentPane);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

This is the custom node built on VBox that should be added to the EquipmentPanels VBox using the method above.

import javafx.fxml.FXML;
import java.io.IOException;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;

public class PaneEquipment extends VBox {

    @FXML   private TextField techId;
    @FXML   private TextField shortText;
    @FXML   private TextArea longDesc;


    public PaneEquipment() {
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setLocation(getClass().getResource("/fxml/PaneEquipment.fxml"));
        fxmlLoader.setController(this);

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


    public void updateFields(String techIdArg, String shortNameArg, String longDescArg) {

        techID.setText(techIdArg);
        shortText.setText(shortNameArg);
        longDesc.setText(longDescArg);

    }

}

FXML for the PaneEquipment objects/nodes:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>

<VBox xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0">
         <children>
            <Label maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0" prefWidth="40.0" text="Tech ID" />
            <TextField fx:id="techID" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0" prefWidth="150.0" promptText="Tech ID Number" />
            <Label layoutX="10.0" layoutY="10.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0" prefWidth="92.0" text="Name" />
            <TextField fx:id="shortText" layoutX="50.0" layoutY="10.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0" prefWidth="465.0" promptText="Short text description (max. 40 characters)" />
         </children>
      </HBox>
      <HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="100.0">
         <children>
            <Label prefHeight="132.0" prefWidth="65.0" text="Description" wrapText="true" />
            <TextArea fx:id="longDesc" prefHeight="100.0" prefWidth="682.0" promptText="Long text description (max. 300 characters)" wrapText="true" />
         </children>
      </HBox>
   </children>
</VBox>

Based on my testing, everything is working fine, except that the equipmentPane's are not displaying when the program runs, I just get a blank scroll pane. The database and linked list work fine. The updatefields method works fine. No exception is printed.

If I replace the equipmentPaneBuiler loop with this, it displays correctly:

try {
    VBox vbox = new VBox();
    Label label = new Label();
    vbox.getChildren().add("text");
    EquipmentPanels.getChildren().add(vbox);
    } catch (Exception e) {
        e.printStackTrace();
    }

So I presume it's an issue with my custom node, but I just can't figure it out.

Upvotes: 0

Views: 779

Answers (1)

fabian
fabian

Reputation: 82461

You did not implement the Custom Component approach 100% correctly.

In your case 2 distinct VBoxes (or VBox-derived objects) exist during the execution of the PaneEquipment constructor. The object being constructed and the VBox created by FXMLLoader. The VBox created by FXMLLoader contains the contents but gets ignored and you only add the empty PaneEquipment.

To implement the approach correctly you need to use PaneEquipment as root and replace the root element of the fxml with <fx:root>

<fx:root type="javafx.scene.layout.VBox" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0">
         <children>
            <Label maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0" prefWidth="40.0" text="Tech ID" />
            <TextField fx:id="TechID" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0" prefWidth="150.0" promptText="Tech ID Number" />
            <Label layoutX="10.0" layoutY="10.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0" prefWidth="92.0" text="Name" />
            <TextField fx:id="ShortText" layoutX="50.0" layoutY="10.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0" prefWidth="465.0" promptText="Short text description (max. 40 characters)" />
         </children>
      </HBox>
      <HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="100.0">
         <children>
            <Label prefHeight="132.0" prefWidth="65.0" text="Description" wrapText="true" />
            <TextArea fx:id="LongDesc" prefHeight="100.0" prefWidth="682.0" promptText="Long text description (max. 300 characters)" wrapText="true" />
         </children>
      </HBox>
   </children>
</fx:root>
public PaneEquipment() {
    FXMLLoader fxmlLoader = new FXMLLoader();
    fxmlLoader.setLocation(getClass().getResource("/fxml/PaneEquipment.fxml"));
    fxmlLoader.setController(this);

    fxmlLoader.setRoot(this); // add this line

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

Upvotes: 2

Related Questions