2016-12-05 4 views
1

Я использую JavaFX, чтобы показать представление из моей игры.Nullpointer при инициализации представления 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; 
    } 

The 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 устанавливаются в контроллер, и я могу работать с ним. Но теперь я получаю Nullpointer, когда вызывается mainApp.get.... Поле mainApp равно null. Я действительно не знаю, что это за сделка, потому что, как я сказал, это сработало так в других проектах.

ответ

2

Действительно просто расширение ответа фабиана. Я согласен с тем, что вы должны создать экземпляр контроллера самостоятельно (удалите fx:controller в FXML, как он сказал). Он позволяет объявлять материал как final, которого вы в противном случае не смогли бы, и избегает необходимости иметь множество настроек в вашем общедоступном API, который вам в противном случае не понадобится.

Возможно, вы переместили много вашего кода initialise в конструктор. Обычно я добавляю код только в initialise, если он напрямую изменяет любой вид виджетов JavaFX.

Это будет выглядеть примерно так:

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.

Вы должны переместить код Разыменования mainApp от метода initialize методы setMainApp, создание экземпляра контроллера с инициализирован mainApp собственности самостоятельно и передать его FXMLLoader перед загрузкой (требуется удаление fx:controller атрибута) или с помощью контроллера завода для инициализации экземпляра контроллера (что, вероятно, является самым сложным из вариантов).

+0

ИТАК поле пустым, потому что поле получает значение после 'Initialize()' вызывается. Я предполагаю, что просто вызов другого метода 'init()' в 'setMainApp()' является неким нечистым, но я предполагаю, что я должен принять его таким образом. Спасибо – Master1114

+0

@ Master1114 Обычным подходом было бы вызвать 'mainApp.getGame (...)' и т. Д. Из метода setMainApp (...) '; но если вы хотите использовать дополнительный метод init(), вам нечего остановить. –

Смежные вопросы