请解释为什么以下情况发生以及我需要更改以使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,具体取决于它的调用位置?
答案 0 :(得分:1)
当您启动应用程序时,然后是&#34; SoC&#34;已创建并且&#34; start()&#34;叫做。因此,myScene在此实例中初始化。
当JavaFx为fxml文件创建控制器时,会创建一个新实例!在那个例子中,myScene为null。 您应该从主应用程序类创建一个单独的控制器类。 或者,将myScene设置为static。
答案 1 :(得分:0)
存储功能changeCSS的位置?你能展示你的项目结构吗?
此功能应位于分配给按钮所在视图的控制器内。