【问题标题】:Using 2D arrays with JavaFX and Scene Builder在 JavaFX 和 Scene Builder 中使用 2D 数组
【发布时间】:2019-04-24 14:23:28
【问题描述】:

我在 Java 中创建了一个程序,我正在尝试使用 JavaFX 为它创建一个 UI。 JavaFX 附带名为 Scene Builder 的软件,它允许您编辑 Java 引用的 FXML 文件以创建 UI 布局。

在 Scene Builder 中,我创建了一系列圆形。这是 FXML 文件的简化版本,只有 4 个圆圈:

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

<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.Circle?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <Circle fx:id="nCircle_0_0" fill="DODGERBLUE" layoutX="100.0" layoutY="120.0" onMouseClicked="#btnClick" onMouseEntered="#circleHover" onMouseExited="#circleLeave" radius="20.0" stroke="BLACK" strokeType="INSIDE" />
      <Circle fx:id="nCircle_0_1" fill="DODGERBLUE" layoutX="150.0" layoutY="120.0" onMouseClicked="#btnClick2" onMouseEntered="#circleHover" onMouseExited="#circleLeave" radius="20.0" stroke="BLACK" strokeType="INSIDE" />
      <Circle fx:id="nCircle_0_2" fill="DODGERBLUE" layoutX="200.0" layoutY="120.0" onMouseEntered="#circleHover" onMouseExited="#circleLeave" radius="20.0" stroke="BLACK" strokeType="INSIDE" />
      <Circle fx:id="nCircle_0_3" fill="DODGERBLUE" layoutX="250.0" layoutY="120.0" onMouseEntered="#circleHover" onMouseExited="#circleLeave" radius="20.0" stroke="BLACK" strokeType="INSIDE" />
   </children>
</AnchorPane>

为了控制这些圆形的外观,我需要在我的 Controller.Java 文件中创建引用它们的变量。我还将变量名称放入二维数组中,因为我需要从我的 Java 程序中的其他二维数组中引用它们:

package sample;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

public class Controller {

    @FXML
    public Button btn;
    public Circle nCircle_0_0, nCircle_0_1, nCircle_0_2, nCircle_0_3;

    public Circle theCircles []  = {nCircle_0_0, nCircle_0_1, nCircle_0_2, nCircle_0_3};
    public Circle [][] circleGrid = new Circle[2][2];

    // get method for circleGrid
    public Circle [][] getcircleGrid(){
        return circleGrid;
    }

    public void makeCircleGrid(){
        int count = 0;
        for (int row = 0; row < 2; row++){
            for (int col = 0; col < 2; col++){
                //theCircles[count] = new Circle();
                circleGrid[row][col] = theCircles[count];
                count += 1;
            }
        }
    }

    protected void printCirclesGrid(Circle [][] theGrid){
        for (int row =0; row < 2; row++){
            System.out.print(row);
            for (int col = 0; col < 2; col++){
                System.out.print("\t" + theGrid [row][col]);
            }
            System.out.println();
        }

    }

    public void circleHover(MouseEvent event){
        Circle value = (Circle)event.getSource();
        value.setStrokeWidth(4);
    }

    public void circleLeave(MouseEvent event){
        Circle value = (Circle)event.getSource();
        value.setStrokeWidth(1);
    }

    @FXML
    public void btnClick(MouseEvent event)    {
        nCircle_0_3.setFill(Color.web("#ed4b00"));

    }

    @FXML
    public void btnClick2(MouseEvent event)    {
        circleGrid[1][0].setFill(Color.web("#ed4b00"));
    }

}

还有一个 Main.java 文件,用于启动 JavaFX 并加载到 FXML 文件中:

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 600, 600));
        primaryStage.show();

        Controller startUp = new Controller();
        startUp.makeCircleGrid();
        startUp.printCirclesGrid(startUp.getcircleGrid());
    }

    public static void main(String[] args) {
        launch(args);
    }
}

我遇到的问题是,我需要将圆的引用存储在 2D 数组中,因为我需要从 Java 程序的其他地方引用和控制它们。我尝试将所有变量名放入 2D 数组中,但 Java 将它们视为 null。

如果您运行上面列出的三个文件,将出现一个带有 4 个蓝色圆圈的窗口。单击第一个圆圈将使最后一个圆圈变为红色。但是,点击第二个圆圈会产生 java.lang.NullPointerException 错误。 (如果它按照我希望的方式工作,它会将倒数第二个圆圈变成红色)。

有人告诉我,我需要初始化 Circle 变量,方法是使其等于一个 Circle 对象实例,然后再将其放入 2D 数组。这将解决二维数组中的空值问题。但是我看不到如何初始化 Controller.java 文件中的 Circle 值,因为 Circle 对象是在 FXML 文件中创建的,而不是在 Controller.java 文件中创建的。有什么方法可以存储和引用在 FXML 文件中创建的对象?

【问题讨论】:

  • 请提供一个minimal reproducible example 来说明问题。注意M - 几个圈就够了,不需要一堆:)
  • 感谢您的建议。我已经编辑了我的问题,因此列出了两个 Java 文件和一个 FXML 文件的完整工作版本。如果运行这些文件,将出现 4 个圆圈。单击第一个圆圈将使最后一个圆圈变为红色。单击第二个圆圈会导致错误。

标签: java javafx fxml scenebuilder


【解决方案1】:

如果您没有遗漏任何重要的信息部分,您的变量似乎永远不会被初始化。

public Circle nCircle_0_0, nCircle_0_1, nCircle_0_2, nCircle_0_3, nCircle_0_4, nCircle_1_0, nCircle_1_1, nCircle_1_2, nCircle_1_3, nCircle_1_4;

这不会创建任何 Circle,它只是定义了一个初始化为 null 的变量。您需要创建一个实例并分配它。

在您执行nCircle_0_0 = new Circle(); 之类的操作之前,nCircle_0_0 将是null,因此您将获得NullPointerException

但最重要的是,在 Java 中,您使用的是引用,而不是“变量名”(除非我们谈论的是反射,这里不是这种情况)。这意味着当您分配对数组的引用并稍后将另一个实例分配给您的nCircle_0_0 时,数组中的对象不会受到影响。你应该阅读(并理解)这个:https://stackoverflow.com/a/40523/2266098

您希望为数组中的每个元素定义变量的原因是什么?为什么不能只在循环中创建实例:

for (int row = 0; row < 5; row++){
    for (int col = 0; col < 5; col++){
        circleGrid[row][col] = new Circle();
    }
}

您将无法通过变量nCircle_0_0 获取值,但无论如何您都使用circleGrid[0][0]

【讨论】:

  • hmm .. 可能遗漏了一些东西(不是 fxml gal ;) - 但是圆形字段是公开的,所以不应该在加载控制器时注入它们吗?显然,只是猜测不完整的问题:)
【解决方案2】:

我发现了问题所在:

我已将说明放入 Main.java 文件中:

        Controller startUp = new Controller();
        startUp.makeCircleGrid();
        startUp.printCirclesGrid(startUp.getcircleGrid());

据我所知,这会创建一个不同的 Controller 类实例。它与 FXML 文件中引用的实例不同。因此,nCircle_0_0 和 nCircle_0_1 等的值在进入数组时被视为 null。

如果我改为触发方法 makeCircleGrid();从我的 FXML 文件中创建的按钮或形状之一,然后完整的对象引用进入数组。因此,它将 nCircle_0_0 和 nCircle_0_1 等的值视为 FXML 文件中的实际 Circle 对象。似乎从 FXML 文件中与之交谈的 Controller 类的实例与我试图从 Main.java 交谈的 Controller 类的实例不同

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-22
    • 2016-07-27
    • 2013-11-21
    • 2017-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多