在JavaFX和Scene Builder中使用2D数组

问题描述 投票:-1回答:2

我用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文件中创建引用它们的变量。我还将变量名称放入2D数组中,因为我需要在我的Java程序中从其他2D数组中引用它们:

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数组中。这将解决2D数组中的空值问题。但是我没有看到如何初始化Controller.java文件中的Circle值,因为Circle对象是在FXML文件中创建的,而不是在Controller.java文件中创建的。有什么方法可以存储和引用在FXML文件中创建的对象吗?

java javafx fxml scenebuilder
2个回答
3
投票

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

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的变量。您需要创建一个实例并进行分配。

直到你做像qazxsw poi这样的事情,qazxsw poi将是qazxsw poi所以你得到nCircle_0_0 = new Circle();

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

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

NullPointerException

您将无法通过变量nCircle_0_0获取值,但无论如何都使用https://stackoverflow.com/a/40523/2266098


0
投票

我发现了问题所在:

我已将指令放入Main.java文件中:

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.