为什么动态添加时 VBox 子项不显示?

Why are VBox children not displaying when added dynamically?

谁能解释一下为什么这不起作用?

循环(应该)在 VBox 内、ScrollPane 内、BorderPane 内(中心位置)创建 VBox 的重复模式,每个使用从数据库中提取的不同数据。

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

这是在 VBox 上构建的自定义节点,应使用上述方法将其添加到 EquipmentPanels VBox。

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 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>

根据我的测试,一切正常,除了 equipmentPane 在程序运行时没有显示,我只是得到一个空白的滚动窗格。数据库和链表工作正常。 updatefields 方法工作正常。没有打印异常。

如果我用这个替换 equipmentPaneBuiler 循环,它会正确显示:

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

所以我认为这是我的自定义节点的问题,但我就是想不通。

您没有 100% 正确地实施自定义组件方法。

在您的情况下,在 PaneEquipment 构造函数的执行期间存在 2 个不同的 VBoxes(或 VBox 派生对象)。正在构造的对象和 FXMLLoader 创建的 VBoxFXMLLoader 创建的 VBox 包含内容但被忽略,您只添加空 PaneEquipment.

要正确实施该方法,您需要使用 PaneEquipment 作为根并将 fxml 的根元素替换为 <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);
    }
}