初始化JavaFX视图时的空指针
我正在使用JavaFX显示游戏中的视图 在调用我的初始化JavaFX视图时的空指针,java,javafx,Java,Javafx,我正在使用JavaFX显示游戏中的视图 在调用我的MainApp类中的方法时,将加载该视图: public class MainApp extends Application { //fields public MainApp() { this.game = new Game(); } //lots of other methods public void showGameView() { try {
MainApp
类中的方法时,将加载该视图:
public class MainApp extends Application {
//fields
public MainApp() {
this.game = new Game();
}
//lots of other methods
public void showGameView() {
try {
System.out.println(game.getPlayer().getCurrentRoom());
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/GameView.fxml"));
AnchorPane GameView = (AnchorPane) loader.load();
rootLayout.setCenter(GameView);
GameViewController controller = loader.getController();
controller.setMainApp(this);
} catch (IOException e) {
e.printStackTrace();
}
}
public Game getGame() {
return game;
}
游戏
对象存储一些信息和东西。控制器的外观如下所示:
public class GameViewController {
private MainApp mainApp;
@FXML
public void initialize() {
mainApp.getGame(). ... //do something else
}
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
}
我一直都是这样做的。当控制器加载时,会在控制器中设置
MainApp
对象,我可以使用它。但是现在,当调用任何mainApp.get…
时,我会得到一个空指针。字段mainApp
为空。我真的不知道这里的交易是什么,因为正如我所说的,它在其他项目中也是这样工作的。控制器类的初始化方法在fxmloader.load
方法调用的末尾被调用,即在调用之前
controller.setMainApp(this);
这意味着此时,mainApp
字段仍然包含null
您必须将代码取消引用mainApp
从initialize
方法移动到setMainApp
方法,自己用initializedmainApp
属性创建控制器实例,并在加载之前将其传递给fxmloader
(需要删除fx:controller
属性)或者使用控制器工厂初始化控制器实例(这可能是最复杂的选项)。实际上只是fabian答案的扩展。我同意您应该自己创建控制器实例(如他所说,删除FXML中的fx:controller
)。它允许您将内容声明为final
,否则您将无法这样做,并且避免在公共API中加载您不需要的setter
您可能会将大量初始化代码移动到构造函数中。如果直接修改任何JavaFX小部件,我通常只将代码放入initialise
它看起来像这样:
public void showGameView() {
try {
System.out.println(game.getPlayer().getCurrentRoom());
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/GameView.fxml"));
loader.setController(new GameViewController(this));
AnchorPane GameView = (AnchorPane) loader.load();
rootLayout.setCenter(GameView);
} catch (IOException e) {
e.printStackTrace();
}
}
及
确定,因此该字段为空,因为该字段是在调用initialize()
之后设置的。我想在setMainApp()
中调用另一个init()
方法有点不干净,但我想我必须这样做。感谢you@Master1114通常的方法是从setMainApp(…)
方法调用mainApp.getGame(…)
etc;但是如果你想要一个额外的init()
方法,没有什么可以阻止你这么做。这看起来是一个非常好而且简单的解决方案。我猜它的风格比我最初在其他答案的评论中所想的更简洁。也谢谢你!
public class GameViewController {
private final MainApp mainApp;
public GameViewController(MainApp mainApp)
{
this.mainApp = mainApp;
}
@FXML
public void initialize() {
mainApp.getGame(). ... //do something else
}