FXML按钮导致nullpointer,硬编码按钮不会

时间:2017-01-20 06:48:00

标签: java javafx-8

请解释为什么以下情况发生以及我需要更改以使FXML按钮的行为与硬编码按钮相同。

我正试图通过按下按钮来动态更改应用程序的CSS。 如果我对控制器中的按钮进行硬编码,一切都按预期工作,但使用FXML时,相同的函数调用会导致null指针。

更新以显示完整代码(无论如何都是小测试程序)。请注意我更改了一些名称,以便于阅读。没有任何功能被更改,但增加的功能同时也是一个弱的解决方法: 控制器:

public class SoC extends Application
{
public Scene    myScene;
Button          btn     = new Button();
@FXML
Button          btnFXHack;
@FXML
Button          btnFXFail;
boolean         flipIt  = false;

// basic function i want to use
public void changeCSS()
{
    if (!flipIt)
    {
        myScene.getStylesheets().remove(0);
        myScene.getStylesheets().add(getClass().getResource("styleTwo.css").toExternalForm());
    }
    else
    {
        myScene.getStylesheets().remove(0);
        myScene.getStylesheets().add(getClass().getResource("styleOne.css").toExternalForm());
    }
    flipIt = !flipIt;
}

// workaround that is fine unless there are more then one scene
public void changeCSSHack(Scene s)
{
    if (!flipIt)
    {
        s.getStylesheets().remove(0);
        s.getStylesheets().add(getClass().getResource("styleTwo.css").toExternalForm());
    }
    else
    {
        s.getStylesheets().remove(0);
        s.getStylesheets().add(getClass().getResource("styleOne.css").toExternalForm());
    }
    flipIt = !flipIt;
}

/**
 * Button one changes CSS on his own scene only, which feels kinda hacked and lame.
 * 
 * @param event
 */
@FXML
private void handleCSSHack(ActionEvent event)
{
    // this button can access his own scene AND use it,....
    changeCSSHack(btnFXHack.getScene());
}

/**
 * Button two tries to change CSS with saved values in the mainController...
 * ...and fails.
 * 
 * @param event
 */
@FXML
private void handleCSSFail(ActionEvent event)
{
    // ...yet this button tells me the SAME scene is null. Yes, the one he is on himself.
    changeCSS();
}

@Override
public void start(Stage primaryStage)
{
    try
    {
        BorderPane pane = (BorderPane)   FXMLLoader.load(getClass().getResource("SoC.fxml"));
        myScene = new Scene(pane);
         myScene.getStylesheets().add(getClass().getResource("styleOne.css").toExternalForm());

        btn = new Button("hardcoded");
        btn.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                changeCSS();
            }
        });
        pane.setCenter(btn);

        primaryStage.setScene(myScene);
        primaryStage.show();
        System.out.println("Started");
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

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

我的部分FXML(主板似乎不喜欢FXML,因此无法完全粘贴)

  <Button fx:id="btnFXHack" mnemonicParsing="false" onAction="#handleCSSHack" text="FX Button Hack" BorderPane.alignment="CENTER" />
  <Button fx:id="btnFXFail" mnemonicParsing="false" onAction="#handleCSSFail" text="FX Button Fail" BorderPane.alignment="CENTER" />

作为旁注:如果我只是通过&#34; children()添加FXML按钮到我的窗格。添加(btnFX)&#34;我现在有两次,但它也有效。我真的更喜欢将我的GUI内容从我的代码中删除,所以我真的很想听听如何解决这个问题。

感谢。

编辑以显示我的结构:

programmfolder
-src
--mainpackage
---controller.java
---.fxml-file
-themes folder
--default.css
--SciFi.css

是的,&#34; /&#34;需要到达.css文件。再次:当硬编码按钮调用时,changeCSS()确实正在工作。所以我怀疑问题是在这一端。

也可以按下FXML按钮进行打印(&#34; stuff&#34;)。现在我感觉他只是没有看到myScene,因此获得了nullpointer。即使是简单的system.out.println(myScene.toString())也会导致FXML按钮的空指针。问题是:为什么同一个对象突然变为null,具体取决于它的调用位置?

2 个答案:

答案 0 :(得分:1)

哦,男孩,现在我知道这个问题是什么。您的控制器也是主要的应用程序类!!!

当您启动应用程序时,然后是&#34; SoC&#34;已创建并且&#34; start()&#34;叫做。因此,myScene在此实例中初始化。

当JavaFx为fxml文件创建控制器时,会创建一个新实例!在那个例子中,myScene为null。 您应该从主应用程序类创建一个单独的控制器类。 或者,将myScene设置为static。

答案 1 :(得分:0)

存储功能changeCSS的位置?你能展示你的项目结构吗?

此功能应位于分配给按钮所在视图的控制器内。