I have created a program in Java and I am trying to create a UI for it with JavaFX. JavaFX comes with software called Scene Builder which allows you to edit an FXML file which is referenced by Java for creating the UI layout.
In Scene Builder I created a series of circle shapes. Here is a simplified version of the FXML file with just 4 circles:
<?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>
In order to control the appearance of these circle shapes I need to create variables referencing them in my Controller.Java file. I also put the variable names into a 2D array because I need to reference them from other 2D arrays in my Java program:
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"));
}
}
There is also a Main.java file that starts up JavaFX and loads in the FXML file:
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);
}
}
The problem that I am having, is that I need to store the references to the circles in a 2D Array, because I need to reference and control them from elsewhere in my Java program. I tried putting all of the variable names into a 2D array, but Java sees them as null.
If you run the three files listed above, a window with 4 blue circles will appear. Clicking on the first circle will make the last circle turn red. However, clicking on the second circle will generate a java.lang.NullPointerException error. (If it had worked the way I was hoping, it would have turned the 2nd last circle red).
I was told that I need to initialise the Circle variable, by making it equal to a Circle object instance before placing it into the 2D array. This would get around the problem of null values in the 2D array. But I don't see how I can initialise the Circle values in the Controller.java file because the Circle objects were created in the FXML file and not in the Controller.java file. Is there some way I can store and reference objects that are created in the FXML file?