首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用FXML替换JavaFX中基于逻辑的GUI

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

Stack Overflow用户
提问于 2020-07-14 23:09:32
回答 2查看 101关注 0票数 0

我使用以下代码在JavaFX中创建TextFields的GridPane

代码语言:javascript
运行
复制
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循环吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-07-15 00:16:15

FXML格式不提供循环方式。

FXML文件应该只描述UI的静态(即非动态)、非重复部分。仅仅使用一个FXML文件和声明81个不同的TextField很快就会变得难以管理,使得UI完全动态化是不可能的。UI的这些部分应该由控制器处理,控制器允许您将Java代码连接到FXML文件。在您的示例中,这些字段可能应该添加到控制器的initialize方法中。例如:

FXML:

代码语言:javascript
运行
复制
<?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>

控制器:

代码语言:javascript
运行
复制
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。但这显然取决于应用程序的其余部分是如何设计的。

票数 4
EN

Stack Overflow用户

发布于 2020-07-15 00:21:40

正如注释和其他答案中所述,没有办法在FXML中模拟循环,并且这种功能应该用Java而不是FXML编写。

请注意,一种模式是创建自定义类来处理您需要在代码中编写的部分。我通常不喜欢仅仅为了添加控件而对布局类进行子类化,尽管在这种情况下,这至少增加了一些功能,并很好地使用了FXML。

TextFieldGrid.java:

代码语言:javascript
运行
复制
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文件中:

代码语言:javascript
运行
复制
<?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>

并以正常方式引用控制器中的功能:

代码语言:javascript
运行
复制
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));
            }
        }
    }

}

为了完整起见,应用程序类:

代码语言:javascript
运行
复制
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();
    }

}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62898248

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档