【问题标题】:Creating a scene using both FXML and the Controller in JavaFX在 JavaFX 中同时使用 FXML 和控制器创建场景
【发布时间】:2017-10-03 13:16:14
【问题描述】:

我在 SceneBuilder 中创建了一个 9x9 GridPane,我想将单独的 TextFields 添加到每个单元格。我确定还有其他方法可以创建这样的大表,但我不是在寻找不同的方法来做到这一点(这是我学习经验的一部分)。我不想在 FXML/SceneBuilder 中添加TextFields;我想在一个数组中跟踪它们,这样我就可以访问它们的各个值,所以我想在控制器中一次创建一个,然后将它们添加到数组以及GridPane 的每个单元格中。

这是我的控制器中尝试添加 TextFields 的部分(我尝试在将它们添加到数组之前创建它们):

@FXML
private GridPane gridPane;
private TextField myTextField[][] = new TextField[9][9];
.
.
.
@Override
public void initialize(URL url, ResourceBundle rb) {
  for (int i = 0; i < 9; ++i){
        for (int j = 0; j < 9; ++j){

            TextField tempTextField = new TextField();
            Font myFont = new Font("System",38);
            tempTextField.setFont(myFont);
            tempTextField.setText(i + ", " + j);
            tempTextField.setPrefSize(70, 70);
            myTextField[i][j] = tempTextField;
            gridPane.add(tempTextField,i,j);
            System.out.println("TextField " +i+j+" Created!");
        }
    } 
}

我在运行前没有收到错误,并且场景没有更新。

编辑:我查看了StackTrace 并注意到我得到了一个空指针

gridPane.add(tempTextField,i,j);

FXML 文件

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="654.0" prefWidth="747.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="sudokusolver.FXMLDocumentController">
    <children>
      <BorderPane prefHeight="654.0" prefWidth="747.0">
         <center>
            <GridPane fx:id="gridPane" gridLinesVisible="true" prefHeight="198.0" prefWidth="200.0" BorderPane.alignment="CENTER">
               <columnConstraints>
              <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
               </columnConstraints>
               <rowConstraints>
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
               </rowConstraints>
            </GridPane>
         </center>
         <bottom>
            <HBox alignment="CENTER" prefHeight="40.0" prefWidth="747.0" BorderPane.alignment="CENTER">
               <children>
                  <FlowPane prefHeight="200.0" prefWidth="200.0">
                     <children>
                        <Button fx:id="loadButton" alignment="CENTER" contentDisplay="CENTER" minHeight="-Infinity" minWidth="-Infinity" onAction="#setGrid" prefHeight="35.0" prefWidth="100.0" text="Load Board" />
                          <Button fx:id="solveButton" alignment="CENTER" contentDisplay="CENTER" minHeight="-Infinity" minWidth="-Infinity" onAction="#sudokuSolve" prefHeight="35.0" prefWidth="100.0" text="Solve" />
                     </children>
                  </FlowPane>
               </children>
            </HBox>
         </bottom>
      </BorderPane>
    </children>
</AnchorPane>

【问题讨论】:

  • 显然gridPane 为空。也许发布 FXML 文件?
  • @James_D 我已经更新了。另外,您能否让我知道更新问题是否会通知发表评论的人。这样我就可以避免像这样无意义的标签/cmets。
  • 不,对问题的编辑没有自动通知(除了其他人编辑您的问题或答案时的通知)。
  • 看起来是正确的。这是您发布的 FXML 的控制器,大概是?而且我假设您没有将它用作任何其他 FXML 文件的控制器,或者以某种方式创建它的任何其他实例?
  • @James_D 我已经解决了这个问题。我对这一切都很陌生,NetBeans 有一个默认的 FXML 文档。我从 SceneBuilder 中删除了一个标签,它没有删除控制器中的对象。它根本没有给我一个标签错误,而是将我引向另一条线。感谢您帮助我理解这一点。

标签: java javafx fxml scenebuilder


【解决方案1】:

尝试在您的控制器中实现javafx.fxml.Initializable 接口,并将setGrid() 逻辑移动到它附带的方法中。

【讨论】:

  • 你不需要实现Initializable(从JavaFX 2.1开始)。只需定义一个方法public void initialize(),它会被反射自动调用。
  • 移动初始化是我之前尝试过的。我再次尝试确定,它不起作用。我可以发布编译时给出的错误,但它很长。似乎存在反射、加载器和空指针异常,但没有一个直接指向我的代码。
  • @Raitab 编辑您的问题以包括您尝试使用initialize() 和完整的堆栈跟踪。我假设如果您遇到空指针异常,您会阅读 stackoverflow.com/questions/218384/… 并尝试修复它们。
  • @James_D - 你是对的,我很清楚这个功能。但是,就我个人而言,我不喜欢我的代码中的“魔法”。这是 JavaFX 开发人员同意的一些约定……但这只是我和我保持“干净代码”的方式:)
  • @MironBalcerzak “如果控制器实现Initializable,调用它的initialize() 方法”和“如果控制器有一个initialize() 方法,调用它”不是一样的约定吗?有优点也有缺点。例如。如果实现接口,则更容易在方法名称中发现拼写错误;但是使用反射方法具有更大的灵活性(如果不需要参数,您可以删除它们,或者如果您对其进行注释,则将方法设为私有等)
猜你喜欢
  • 1970-01-01
  • 2014-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多