用FXML替换JavaFX中基于逻辑的GUI

我正在使用以下代码在JavaFX中创建GridPane的{​​{1}}:

TextField

GridPane grid = new GridPane(); for (int i = 0; i < 9; i++) for (int j = 0; j < 9; j++) { grid.add(createTextField(),j,i); } } 是我制作的一种方法,它返回具有我设置的某些属性的createTextField()

我想开始使用FXML文件在JavaFX中创建我的GUI,但是我不太了解如何用XML文件替换Java逻辑。如何使用FXML重新创建上述代码? FXML是否有for循环?

iCMS 回答:用FXML替换JavaFX中基于逻辑的GUI

FXML格式没有提供循环的方法。

FXML文件应仅描述UI的静态(即非动态),非重复部分。仅使用FXML文件就不可能使UI完全动态,例如,声明81个不同的TextField很快就变得难以管理。 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。但这显然取决于应用程序其余部分的设计方式。

,

如评论和其他答案中所述,无法模仿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,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,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://www.f2er.com/1937658.html

大家都在问