Trouble looping through FXML elements and adding some of them to a list

Umbrella_Programmer :

I found this question very helpful, but I'm still having difficulty getting my loop to work correctly.

EXPECTATION:

I'm building a simple JavaFX app with a UI that takes inputs through a few TextFields and a few buttons. I've built a "Reset" button that should clear the text from all the TextFields, but I cannot get it to work.

The button's method loops over the FXML elements, and I expect it to identify TextFields and add them to a list:

private List<TextField> identifyTextFields(Pane parent) {

    List<TextField> textFieldList = new ArrayList<>();

    for (Node element : parent.getChildren()) {

        if (element instanceof Pane) {
            // if element is a container, scan its children
            scanNodesForTextFields((Pane) element);

            //This line is always false. Why?
            if (element instanceof TextField) {

                textFieldList.addAll(scanNodesForTextFields((Pane) element));
            }


        } else if (element instanceof TextField) {

            textFieldList.add((TextField) element);
        }
    }

    return textFieldList;
}

Then, the textFieldList is returned to this method, where the textFields are looped through and cleared:

 @FXML
public void resetButtonClicked(ActionEvent event) {

    List<TextField> textFieldList = identifyTextFields(parentNode);

    for (TextField textField : textFieldList) {

        textField.setText("");
    }

}

REALITY:

In the

identifyTextFields(Pane parent)

method, this line is always false:

if (element instanceof TextField) {

I do not understand why. I'm trying to loop through all of the elements of the FXML scene graph, beginning with the root node, which is an Anchor Pane. If the inner loop finds that one of the elements is a TextField, it should be added to a list...but it will never find any TextFields.

I'm also having a little trouble understanding the results of debugging, but it looks to me like the method isn't even accessing the TextFields; it's as if it skips right over them.

What's wrong with my method?

For reference, here is the piece of the scene graph that includes the 6 TextFields I'm targeting:

<AnchorPane fx:id="parentNode" prefHeight="758.0" 
prefWidth="662.0" xmlns="http://javafx.com/javafx/8.0.171" 
xmlns:fx="http://javafx.com/fxml/1" 
fx:controller="Controller">
   <children>
  ...snip...
       <HBox fx:id="textFieldContainer" layoutY="378.0" prefHeight="100.0" prefWidth="660.0">
                 <children>
                    <VBox prefHeight="100.0" prefWidth="110.0">
                       <children>
                          <Label text="1">
                             <padding>
                                <Insets left="30.0" />
                             </padding>
                             <font>
                                <Font name="Calibri" size="16.0" />
                             </font>
                          </Label>
                          <TextField fx:id="textFieldOne">
                             <VBox.margin>
                                <Insets top="10.0" />
                             </VBox.margin>
                          </TextField>
                       </children>
                    </VBox>
                    <VBox prefHeight="100.0" prefWidth="110.0">
                       <children>
                          <Label text="2">
                             <padding>
                                <Insets left="30.0" />
                             </padding>
                             <font>
                                <Font name="Calibri" size="16.0" />
                             </font>
                          </Label>
                          <TextField fx:id="textFieldTwo">
                             <VBox.margin>
                                <Insets top="10.0" />
                             </VBox.margin>
                          </TextField>
                       </children>
                    </VBox>
                    <VBox prefHeight="200.0" prefWidth="110.0">
                       <children>
                          <Label text="3">
                             <padding>
                                <Insets left="30.0" />
                             </padding>
                             <font>
                                <Font name="Calibri" size="16.0" />
                             </font>
                          </Label>
                          <TextField fx:id="textFieldThree">
                             <VBox.margin>
                                <Insets top="10.0" />
                             </VBox.margin>
                          </TextField>
                       </children>
                    </VBox>
                    <VBox prefHeight="200.0" prefWidth="110.0">
                       <children>
                          <Label text="4">
                             <padding>
                                <Insets left="30.0" />
                             </padding>
                             <font>
                                <Font name="Calibri" size="16.0" />
                             </font>
                          </Label>
                          <TextField fx:id="textFieldFour">
                             <VBox.margin>
                                <Insets top="10.0" />
                             </VBox.margin>
                          </TextField>
                       </children>
                    </VBox>
                    <VBox prefHeight="200.0" prefWidth="110.0">
                       <children>
                          <Label text="5">
                             <padding>
                                <Insets left="30.0" />
                             </padding>
                             <font>
                                <Font name="Calibri" size="16.0" />
                             </font>
                          </Label>
                          <TextField fx:id="textFieldFive">
                             <VBox.margin>
                                <Insets top="10.0" />
                             </VBox.margin>
                          </TextField>
                       </children>
                    </VBox>
                    <VBox prefHeight="200.0" prefWidth="110.0">
                       <children>
                          <Label text="6">
                             <padding>
                                <Insets left="30.0" />
                             </padding>
                             <font>
                                <Font name="Calibri" size="16.0" />
                             </font>
                          </Label>
                          <TextField fx:id="textFieldSix">
                             <VBox.margin>
                                <Insets top="10.0" />
                             </VBox.margin>
                          </TextField>
                       </children>
                    </VBox>
                 </children></HBox>
           ...snip...
jewelsea :

You can use a lookup based upon a CSS selector for the "TextField" css type to find all text fields recursively for a given parent node.

@SuppressWarnings("unchecked")
private Set<TextField> lookupTextFields(Parent parent) {
    return (Set<TextField>)(Set<?>) parent.lookupAll("TextField");
}

The odd type casting is from:


Sometimes, for lookups to function correctly, you need to generate a layout pass; see:

This is done by calling the following, prior to calling lookupAll:

parent.applyCss();
parent.layout();

However, for your particular situation it is unlikely that generating a layout pass is necessary. The FXML loader will already have constructed enough of the scene graph during the FXML load call that a lookup based upon a "TextField" css selector will work.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=165485&siteId=1