为什么动态添加时 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 个不同的 VBox
es(或 VBox
派生对象)。正在构造的对象和 FXMLLoader
创建的 VBox
。 FXMLLoader
创建的 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);
}
}
谁能解释一下为什么这不起作用?
循环(应该)在 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 个不同的 VBox
es(或 VBox
派生对象)。正在构造的对象和 FXMLLoader
创建的 VBox
。 FXMLLoader
创建的 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);
}
}