带有文本字段和复选框的动态网格窗格

Dynamic Gridpane with TextFields and Checkboxes

我正在处理一个项目,其中有 2 个选项卡。在第一个选项卡的用户界面上有一个文本字段和一个按钮。在文本字段中,用户可以写任何数字直到 100,当他按下按钮时,我的应用程序将转到下一个选项卡,其中有一个包含三列 A、B 和 C 的网格窗格。

所以我想要的是用户将根据该数字在第一个选项卡的文本字段中输入的任何数字,它应该在第二个选项卡的网格窗格中添加与文本字段、复选框和日期选择器相同数量的行。

使用 SceneBuilder 可以很容易地创建固定大小的网格窗格,然后在其中添加元素并给它们 fx:id,但动态它很复杂,因为我必须将 fx:id 分配给每个文本字段,复选框和日期选择器,这样我就可以检索它的数据并可以发送到数据库。

我应该使用 Gridpane 还是有任何其他解决方案来实现目标。如果有人可以指导我需要做什么,那将是很大的帮助。

您不能在 fxml 文件中使用循环日志。但是,您可以实现一些逻辑来添加指定数量的行。 <fx:root> 元素可用于为各个行创建 fxml 文件:

main.fxml

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

<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.text.Text?>

<GridPane fx:id="root" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxml.grid.MainController">
    <children>
        <Text text="A"/>
        <Text text="B" GridPane.columnIndex="1"/>
        <Text text="C" GridPane.columnIndex="2"/>
    </children>
</GridPane>

sub.fxml

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

<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.DatePicker?>

<fx:root type="javafx.scene.layout.GridPane" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxml.grid.SubController">
    <children>
        <TextField fx:id="text" GridPane.columnIndex="0" GridPane.rowIndex="$rowIndex" />
        <CheckBox fx:id="checkBox" GridPane.columnIndex="1" GridPane.rowIndex="$rowIndex" />
        <DatePicker fx:id="datePicker" GridPane.columnIndex="2" GridPane.rowIndex="$rowIndex" />
    </children>
</fx:root>

主控制器

public class MainController {

    @FXML
    private GridPane root;

    private final List<SubController> subControllers = new ArrayList<>();

    public void setRowNumber(int rows) throws IOException {
        if (rows < subControllers.size()) {
            // for simplicity only allow the number of rows to grow
            throw new IllegalArgumentException();
        }
        for (int i = subControllers.size(); i < rows; i++) {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("sub.fxml"));

            // add rowIndex to be used from fxml using $rowIndex
            loader.getNamespace().put("rowIndex", subControllers.size() + 1);

            loader.setRoot(root);
            loader.load();
            subControllers.add(loader.getController());
        }
    }

}

子控制器

public class SubController {
    @FXML
    private TextField text;
    @FXML
    private CheckBox checkBox;
    @FXML
    private DatePicker datePicker;

}

使用

int num = 6;
FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
Parent parent = loader.load();
loader.<MainController>getController().setRowNumber(num);

向控制器添加方法以访问单个元素应该不会太难。

请注意 TableView 也值得一看。