0
votes

I started to use days ago JavaFX.

I'd like to make a 3x6 button matrix using GridPane. I made the GridPane on Scene Builder and I want to add dinamically all buttons like this:

@FXML
private GridPane gridPane;
private Parent root;
private Button gridButtons[][];

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

@Override
public void start(Stage stage) throws Exception{
    root = FXMLLoader.load(getClass().getResource("Main.fxml"));

    gridButtons = new Button[3][6];

    for(int x = 0; x < 3; x++) {
        for(int y = 0; y < 6; y++) {
            gridButtons[x][y] = new Button("n");
            gridPane.add(gridButtons[x][y], y, x);
        }
    }

    stage.setTitle("JavaFX 3x6 Matrix");
    stage.setScene(new Scene(root));
    stage.show();
}

But when I try to run this code I get some errors:

Exception in Application start method
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
    at view.Main.start(Main.java:43)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    ... 1 more
Exception running application view.Main

Why this happens?

EDIT:

When I went home I saw again my code and I noticed I made a big mistake. I forgot to write fx:id="gridPane" in the fxml.

Anyway I divided my code in Main and Controller. Thanks for the suggestion.

1
Your gridPane is only initialized in the controller; start() is called on the instance of Main that is created when you launch the application (I.e.start() is not being called on the controller). Don’t use the Application subclass (Main) as the controller - create a separate controller class and initialize your button there. - James_D

1 Answers

0
votes

If you´re using your Main class as a controller too you´ll have to first get the Controller that was created on calling FXMLLoader.load as it creates a new instance of it I'm pretty sure (but in reality you´d never do that anyway, as James_D said you should make a seperate Controller class).

As a quick fix for that code, you can make a method called initialize() that will be called (if that exact method, called exactly that exists) when creating the Scene before it´s displayed. That one will be called in the correct instance of the controller for sure. To be able to pass parameters to the Scene´s Controller, you will have to get the Controller from the FXMLLoader and then call a method in that controller that takes the params as there is no predefined function like initialize for that.

What controller did you (or your SceneBuilder) specify in the FXML though? Can´t imagine that SceneBuilder would pick the Main class as it´s controller. Also, maybe it´s good to stop using SceneBuilder at the start, or else you´ll be lost if it breaks in some way or ends up not doing what you want it to do.