我使用以下代码在JavaFX中创建TextFields的GridPane:
GridPane grid = new GridPane();
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++) {
grid.add(createTextField(), j, i);
}
}createTextField()是我创建的一个方法,它返回具有我设置的某些属性的TextField。
我想开始使用FXML文件在JavaFX中创建GUI,但我不太明白如何用XML文件替换Java逻辑。如何使用FXML重新创建上述代码?FXML有for循环吗?
发布于 2020-07-15 00:16:15
FXML格式不提供循环方式。
FXML文件应该只描述UI的静态(即非动态)、非重复部分。仅仅使用一个FXML文件和声明81个不同的TextField很快就会变得难以管理,使得UI完全动态化是不可能的。UI的这些部分应该由控制器处理,控制器允许您将Java代码连接到FXML文件。在您的示例中,这些字段可能应该添加到控制器的initialize方法中。例如:
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.GridPane?>
<GridPane fx:id="grid" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
hgap="3" vgap="3" alignment="CENTER" fx:controller="com.example.Controller">
<padding>
<Insets topLeftBottomRight="5"/>
</padding>
</GridPane>控制器:
package com.example;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
public class Controller {
@FXML private GridPane grid;
private TextField[][] fields;
@FXML
private void initialize() {
grid.addEventFilter(KeyEvent.KEY_PRESSED, this::handleArrowNavigation);
fields = new TextField[9][9];
for (int i = 0; i < fields.length; i++) {
for (int j = 0; j < fields[0].length; j++) {
fields[i][j] = createTextField();
grid.add(fields[i][j], j, i);
}
}
}
private TextField createTextField() {
// ...
}
private void handleArrowNavigation(KeyEvent event) {
// ...
}
}由于这似乎与your previous question有关,因此我还展示了如何添加事件过滤器,因为在FMXL文件中无法做到这一点(只能设置onXXX事件处理程序属性)。
在本例中,可能不值得使用FXML,因为您实际上只是使用FXML来声明一个GridPane。但这显然取决于应用程序的其余部分是如何设计的。
发布于 2020-07-15 00:21:40
正如注释和其他答案中所述,没有办法在FXML中模拟循环,并且这种功能应该用Java而不是FXML编写。
请注意,一种模式是创建自定义类来处理您需要在代码中编写的部分。我通常不喜欢仅仅为了添加控件而对布局类进行子类化,尽管在这种情况下,这至少增加了一些功能,并很好地使用了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;
}
}您可以使用它,例如在FXML文件中:
<?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>并以正常方式引用控制器中的功能:
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));
}
}
}
}为了完整起见,应用程序类:
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();
}
}https://stackoverflow.com/questions/62898248
复制相似问题