我用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文件中创建的对象吗?
如果您没有省略任何重要的信息部分,那么您的变量似乎永远不会被初始化。
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。
我发现了问题所在:
我已将指令放入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类的实例不同。