2016-12-05 65 views
1

我正在使用JavaFX來顯示我的遊戲中的視圖。初始化JavaFX視圖時的空指針

當我打電話,我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; 
    } 

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爲空。我真的不知道這筆交易在這裏,因爲我說在其他項目中這樣工作。

回答

2

真的只是fabian的答案的延伸。我同意你應該自己創建控制器實例(如他所說,刪除FXML中的fx:controller)。它允許你聲明final,否則你不能這樣做,並且避免你必須在你的公共API中加載大量的setter,否則你將不需要這些setter。

您可能會將很多initialise代碼移入構造函數中。如果它直接修改任何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(); 
    } 
} 

public class GameViewController { 

    private final MainApp mainApp; 

    public GameViewController(MainApp mainApp) 
    { 
     this.mainApp = mainApp; 
    } 

    @FXML 
    public void initialize() { 
     mainApp.getGame(). ... //do something else 
    } 
+0

這看起來像一個非常好的和簡單的解決方案。我想它比我在其他答案的評論中首先想到的更清晰的風格。謝謝你! – Master1114

3

控制器類的initialize方法是在FXMLLoader.load方法調用,即結束時,你做

controller.setMainApp(this); 

這意味着此時的mainApp字段仍然包含null之前調用。

你必須移動代碼從initialize方法解引用mainAppsetMainApp方法,以初始化mainApp屬性創建控制器實例自己,並加載之前將它傳遞給FXMLLoader(需要去除fx:controller屬性)或使用控制器工廠初始化控制器實例(這可能是最複雜的選項)。

+0

好了,所以因爲'初始化()'被調用後場被設置的字段爲空。我想只是在'setMainApp()'中調用另一個'init()'方法是某種不清潔的,但我想我必須這樣做。謝謝 – Master1114

+0

@ Master1114通常的做法是從'setMainApp(...)'方法調用'mainApp.getGame(...)'等;但如果你想要一個額外的'init()'方法,沒有什麼可以阻止你這樣做。 –