As stated in the comments and the other answer, there's no way to mimic loops in FXML, and this kind of functionality should be written in Java rather than FXML.
Note that one pattern is to create a custom class to handle the parts you need to write in code. I generally dislike subclassing layout classes solely for the purpose of adding controls to them, though in this case this does at least add some functionality, as well as playing nicely with FXML.
TextFieldGrid.java:
package org.jamesd.examples.textfieldgrid;
import javafx.beans.NamedArg;
import javafx.beans.property.StringProperty;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
public class TextFieldGrid extends GridPane {
private final StringProperty[][] text ;
public TextFieldGrid(
@NamedArg("numberOfColumns") int numberOfColumns,
@NamedArg("numberOfRows") int numberOfRows
) {
text = new StringProperty[numberOfColumns][numberOfRows];
for (int i = 0 ; i < numberOfRows ; i++) {
for (int j = 0 ; j < numberOfColumns ; j++) {
TextField textField = new TextField();
add(textField, j, i);
text[j][i] = textField.textProperty();
}
}
}
public StringProperty textProperty(int column, int row) {
return text[column][row];
}
public final String getText(int column, int row) {
return textProperty(column, row).get();
}
public final void setText(int column, int row, String text) {
textProperty(column, row).set(text);
}
public int getNumberOfColumns() {
return text.length;
}
public int getNumberOfRows() {
return text[0].length;
}
}
Which you can use, e.g. in an FXML file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import org.jamesd.examples.textfieldgrid.TextFieldGrid?>
<BorderPane xmlns="http://javafx.com/javafx/8.0.171"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="org.jamesd.examples.textfieldgrid.Controller">
<top>
<Label text="Enter 81 values below:" />
</top>
<center>
<TextFieldGrid fx:id="textFieldGrid" numberOfColumns="9" numberOfRows="9" />
</center>
<bottom>
<Button text="Check values" onAction="#checkValues" />
</bottom>
</BorderPane>
and reference the functionality in the normal way in the controller:
package org.jamesd.examples.textfieldgrid;
import javafx.fxml.FXML;
public class Controller {
@FXML
private TextFieldGrid textFieldGrid ;
@FXML
private void checkValues() {
for (int i = 0 ; i < textFieldGrid.getNumberOfColumns(); i++) {
for (int j = 0; j < textFieldGrid.getNumberOfRows(); j++) {
System.out.printf("[%d, %d]: %s%n", i, j, textFieldGrid.getText(i, j));
}
}
}
}
Just for completeness, the application class:
package org.jamesd.examples.textfieldgrid;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class App extends Application {
@Override
public void start(Stage stage) throws IOException {
Scene scene = new Scene(FXMLLoader.load(getClass().getResource("TextFieldGrid.fxml")));
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}