从网格窗格

时间:2018-06-04 23:51:58

标签: java javafx gridpane

我试图在用户可以输入数字的每一行上创建一个带有文本框的网格,并添加相应数量的新行。这很有效,如下面的屏幕截图所示。 enter image description here

现在我试图从基于问题创建的那些文本字段中提取文本"有多少?"因为它们嵌套在各种节点元素中,所以我很难确定正确的方法。任何人都可以告诉我我做错了什么?我尝试使用保存按钮测试它,但我总是在我的控制台上进入else "Vboxgrid2 is empty!"语句。我不知道为什么它说我的VBoxgrid2是空的!

以下是我重新创建的最小,完整且可验证的示例:

package testing;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ExtractThatText extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("GridPane Experiment");
        GridPane gridPane = new GridPane();

        for(int i=0;i<5;i++) {
            VBox mainVBox = new VBox(); 
            VBox vboxgrid1 = new VBox();
            VBox vboxgrid2 = new VBox();
            HBox hboxgrid = new HBox();
            hboxgrid.setPadding(new Insets(5,5,5,5));

            RadioButton rbYes = new RadioButton("Yes");
            RadioButton rbNo = new RadioButton("No");
            Label howmanyLabel = new Label("   How many?   ");
            TextField howManytxtB = new TextField();

            hboxgrid.getChildren().add(rbYes);
            hboxgrid.getChildren().add(rbNo);
            hboxgrid.getChildren().add(howmanyLabel);
            hboxgrid.getChildren().add(howManytxtB);

            vboxgrid1.getChildren().add(hboxgrid);

            howManytxtB.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    vboxgrid2.getChildren().clear();
                    Integer howManyNum = Integer.valueOf(howManytxtB.getText());
                    for(int row=0;row<howManyNum;row++) {
                        //creating rows for entering the new entities
                        HBox innerRowbox = new HBox();
                        TextField name = new TextField();
                        ComboBox cb = new ComboBox(); //empty cb for now
                        name.setPromptText("Enter name of the new Entity");
                        name.setMinWidth(200);
                        innerRowbox.getChildren().add(name);
                        innerRowbox.getChildren().add(cb);
                        vboxgrid2.getChildren().add(innerRowbox);
                    }
                }

            });

            mainVBox.getChildren().add(vboxgrid1);
            mainVBox.getChildren().add(vboxgrid2);
            gridPane.add(mainVBox,1, i);
        }

        for(int i=0;i<5;i++) {
            gridPane.add(new Label("row"+i), 0 , i);
        }

        Button saveButton = new Button("save content");

        saveButton.setOnAction(e-> {
            Node mainVBox = gridPane.getChildren().get(1); //get just the first row's 1th column which contains mainVBox
            if(mainVBox instanceof VBox) { 
                Node vboxgrid2 = ((VBox) mainVBox).getChildren().get(1);

                if(vboxgrid2 instanceof VBox) {

                    if(!((VBox) vboxgrid2).getChildren().isEmpty()) {

                        Node innerRowBox = ((VBox) vboxgrid2).getChildren().get(0);
                        if(innerRowBox instanceof HBox) {

                            for(Node howmanyTB:((HBox)innerRowBox).getChildren()) {
                                if(howmanyTB instanceof TextField) {
                                    System.out.println(((TextField) howmanyTB).getText()); //content to save, extracted from the dnamic textfields created.
                                }
                                else System.out.println("howmanyTB not an instance of TextField error!");
                            }
                        }
                        else    System.out.println("innerRowBox not an instance of HBox error!");
                    }
                    else System.out.println("Vboxgrid2 is empty!");
                }
                else System.out.println("vboxgrid2 not an instance of VBox error!");
            } 
            else    System.out.println("mainVbox not an instance of VBox error!");
        });

        gridPane.add(saveButton, 1, 5);
        gridPane.setHgap(10);
        gridPane.setVgap(10);
        Scene scene = new Scene(gridPane, 500, 500);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }       
}

**如果我很难理解所有节点的嵌套,这里有一个摘要:

gridPane - &gt; mainVBox(在第二/第一列的每一行) - &gt; vboxgrid2(以及vboxgrid1内的mainVBox以及innerRowbox中的无线电按钮行 - &gt; name - &gt; public static String read(){ return (new Scanner(System.in)).nextLine(); } (文本框)

2 个答案:

答案 0 :(得分:2)

  

如果难以理解我所有节点的嵌套

由于您似乎意识到您的嵌套有点令人困惑,因此最好将TextField保存在比场景层次结构更容易访问的数据结构中。在这种情况下,由于项目数量在创建之前是已知的,因此可以使用TextField[][]数组,但您也可以使用List<List<TextField>>来动态添加(内部)行。 / p>

顺便说一句:既然您使用索引1就可以访问第二行,而不是第一行。

仅使用VBox来包含HBox似乎是不必要的。您可以直接使用HBox,因为VBox没有其他孩子。

Label howmanyLabel = new Label("   How many?   ");

最好使用此间距的余量而不是空格。

@Override
public void start(Stage primaryStage) throws Exception {
    primaryStage.setTitle("GridPane Experiment");
    GridPane gridPane = new GridPane();

    final int rowCount = 5;
    TextField[][] textFields = new TextField[rowCount][0];
    final Insets hboxPadding = new Insets(5);
    final Insets labelMargin = new Insets(0, 15, 0, 15);

    for (int i = 0; i < rowCount; i++) {
        VBox vboxgrid2 = new VBox();

        RadioButton rbYes = new RadioButton("Yes");
        RadioButton rbNo = new RadioButton("No");
        Label howmanyLabel = new Label("How many?");
        HBox.setMargin(howmanyLabel, labelMargin);
        TextField howManytxtB = new TextField();

        HBox hboxgrid = new HBox(rbYes, rbNo, howmanyLabel, howManytxtB);
        hboxgrid.setPadding(hboxPadding);

        final int rowIndex = i;

        howManytxtB.setOnAction(event -> {
            vboxgrid2.getChildren().clear();
            int howManyNum = Math.max(0, Integer.parseInt(howManytxtB.getText()));
            TextField[] fields = new TextField[howManyNum];
            for (int row = 0; row < howManyNum; row++) {
                //creating rows for entering the new entities
                TextField name = new TextField();
                ComboBox cb = new ComboBox(); //empty cb for now
                name.setPromptText("Enter name of the new Entity");
                name.setMinWidth(200);
                HBox innerRowbox = new HBox(name, cb);
                vboxgrid2.getChildren().add(innerRowbox);

                fields[row] = name;
            }
            textFields[rowIndex] = fields;
        });

        VBox mainVBox = new VBox(hboxgrid, vboxgrid2);
        gridPane.addRow(i, new Label("row" + i), mainVBox);
    }

    Button saveButton = new Button("save content");

    saveButton.setOnAction(e -> {
        TextField[] secondRowFields = textFields[1];
        if (secondRowFields.length == 0) {
            System.out.println("no TextFields in row1");
        } else {
            for (TextField textField : secondRowFields) {
                System.out.println(textField.getText());
            }
        }
    });

    gridPane.add(saveButton, 1, rowCount);
    gridPane.setHgap(10);
    gridPane.setVgap(10);
    Scene scene = new Scene(gridPane, 500, 500);
    primaryStage.setScene(scene);
    primaryStage.show();
}

答案 1 :(得分:1)

在演示应用中,我添加了List<TextField> textFieldContainer = new ArrayList();,用于存储动态创建TextFields

如果数字发生变化且按下了 Enter ,则下面的代码会删除相应的TextFields

textFieldContainer.removeIf(p -> p.getUserData().toString().startsWith("TextField_" + tempRow));
  

完整代码:

import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ExtractThatText extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        List<TextField> textFieldContainer = new ArrayList();

        primaryStage.setTitle("GridPane Experiment");
        GridPane gridPane = new GridPane();

        for(int i=0;i<5;i++) {
            VBox mainVBox = new VBox(); 
            VBox vboxgrid1 = new VBox();
            VBox vboxgrid2 = new VBox();
            HBox hboxgrid = new HBox();
            hboxgrid.setPadding(new Insets(5,5,5,5));

            RadioButton rbYes = new RadioButton("Yes");
            RadioButton rbNo = new RadioButton("No");
            Label howmanyLabel = new Label("   How many?   ");
            TextField howManytxtB = new TextField();

            hboxgrid.getChildren().add(rbYes);
            hboxgrid.getChildren().add(rbNo);
            hboxgrid.getChildren().add(howmanyLabel);
            hboxgrid.getChildren().add(howManytxtB);

            vboxgrid1.getChildren().add(hboxgrid);

            final Integer tempRow = i;
            howManytxtB.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    vboxgrid2.getChildren().clear();
                    Integer howManyNum = Integer.valueOf(howManytxtB.getText());

                    //The next two lines clears TextFields if you change the amount and/or press enter
                    textFieldContainer.removeIf(p -> p.getUserData().toString().startsWith("TextField_" + tempRow));
                    for(int row=0;row<howManyNum;row++) {
                        //creating rows for entering the new entities
                        HBox innerRowbox = new HBox();
                        TextField name = new TextField();
                        final Integer innerRow = row;
                        name.setUserData("TextField_" + tempRow + "_" + innerRow);
                        System.out.println(name.getUserData().toString());
                        textFieldContainer.add(name);
                        ComboBox cb = new ComboBox(); //empty cb for now
                        name.setPromptText("Enter name of the new Entity");
                        name.setMinWidth(200);
                        innerRowbox.getChildren().add(name);
                        innerRowbox.getChildren().add(cb);
                        vboxgrid2.getChildren().add(innerRowbox);
                    }
                }

            });

            mainVBox.getChildren().add(vboxgrid1);
            mainVBox.getChildren().add(vboxgrid2);
            gridPane.add(mainVBox,1, i);
        }

        for(int i=0;i<5;i++) {
            gridPane.add(new Label("row"+i), 0 , i);
        }

        Button saveButton = new Button("save content");

        saveButton.setOnAction(e-> {
            System.out.println("Saving these TextField's Text:");
            for(TextField textField : textFieldContainer)
            {
                System.out.println(textField.getUserData() + ": " + textField.getText());
            }
        });

        gridPane.add(saveButton, 1, 5);
        gridPane.setHgap(10);
        gridPane.setVgap(10);
        Scene scene = new Scene(gridPane, 500, 500);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }       
}
  

输出:

enter image description here

  

点击保存内容,查看TextFields中当前的信息。

Saving these TextField's Text:
TextField_0_0: one
TextField_1_0: two
TextField_1_1: three
TextField_2_0: four
TextField_3_0: seven
TextField_3_1: six
TextField_4_0: five