【问题标题】:Adding buttons to GridPane while using FXML使用 FXML 时向 GridPane 添加按钮
【发布时间】:2018-05-27 03:12:28
【问题描述】:

我几天前就开始使用 JavaFX。

我想使用 GridPane 制作一个 3x6 按钮矩阵。 我在 Scene Builder 上制作了 GridPane,我想动态添加所有按钮,如下所示:

@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();
}

但是当我尝试运行这段代码时,我得到了一些错误:

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

为什么会这样?

编辑:

当我回到家时,我再次看到了我的代码,我发现我犯了一个大错误。我忘了在 fxml 中写 fx:id="gridPane"。

无论如何,我将代码分为 Main 和 Controller。谢谢你的建议。

【问题讨论】:

  • 你的gridPane只在控制器中初始化; start() 在您启动应用程序时创建的Main 实例上调用(即start() 不在控制器上调用)。不要使用 Application 子类 (Main) 作为控制器 - 创建一个单独的控制器类并在那里初始化您的按钮。

标签: java javafx


【解决方案1】:

如果您也将 Main 类用作控制器,则您必须首先获取在调用 FXMLLoader.load 时创建的 Controller,因为它会创建它的新实例(但实际上您无论如何都不会这样做,因为 James_D 说你应该创建一个单独的 Controller 类)。

作为该代码的快速修复,您可以创建一个名为initialize() 的方法,在创建场景之前,该方法将被调用(如果该方法完全存在,则调用该方法)。肯定会在控制器的正确实例中调用那个。为了能够将参数传递给场景的控制器,您必须从 FXMLLoader 中获取控制器,然后在该控制器中调用一个获取参数的方法,因为没有像初始化这样的预定义函数。

您(或您的 SceneBuilder)在 FXML 中指定了什么控制器?无法想象 SceneBuilder 会选择 Main 类作为它的控制器。另外,一开始就停止使用 SceneBuilder 可能会很好,否则如果它以某种方式中断或最终没有做你想做的事情,你会迷失方向。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多