title: JavaFX - Loading/creating multiple controllers
body: <p>I have researched this for a couple hours now, and even though there is a lot about "multiple controllers", none of the solutions worked for my problem. I don't know if I am just structuring my program wrong, so I need some input.</p>
  
  <p>I got a "MainView" (<code>App</code> class with <code>AppView</code> and <code>AppController</code>) and a "SubView" (<code>SubView</code> and <code>SubViewController</code>). In <code>App</code>, I am loading the <code>mainView</code> as <code>primaryStage</code> and loading the <code>AppController</code>. I created a <code>stageManager</code> class to handle different views. My problem is: Where and how do I create/load my <code>subViewController</code>?</p>
  
  <pre><code>public class App extends Application {
  
      private Stage primaryStage;
      private AnchorPane rootLayout;
      private AppController appController;
  
      MainModel model = new MainModel();
      StageManager stageManager;
  
      @Override
      public void start(Stage primaryStage) {
          this.primaryStage = primaryStage;
          this.primaryStage.setTitle("App");
  
          initRootLayout();
          appController.initModel(model);
          appController.setStageManager(stageManager);
      }
  
      public void initRootLayout() {
          try {
              FXMLLoader loader = new FXMLLoader();
              loader.setLocation(getClass().getResource("mainView.fxml"));
              rootLayout = (AnchorPane) loader.load();
              appController = loader.&lt;AppController&gt;getController();
  
              Scene scene = new Scene(rootLayout);
              primaryStage.setScene(scene);
              primaryStage.show();
  
              stageManager = new StageManager(primaryStage, rootLayout, appController);
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
  
      public static void main(String[] args) {
          launch(args);
      }
  }
  
  
  
  
  public class AppController implements Initializable {
  
      private MainModel model;
      private StageManager stageManager;
  
      @FXML
      private Button btn;
  
      @FXML
      private void handleButtonAction(ActionEvent event) {
          stageManager.changeScene("subView.fxml");
      }
  
      @Override
      public void initialize(URL url, ResourceBundle rb) {
      }   
  
      public void initModel(MainModel model) {
          this.model = model;
      }
  
      public void setStageManager(StageManager stageManager){
          this.stageManager = stageManager;
      }
  }
  
  
  public class StageManager {
  
      private Stage primaryStage;
      private AnchorPane rootLayout;
      private AppController appController;
  
      public StageManager(Stage primaryStage, AnchorPane rootLayout, AppController appController){
          this.primaryStage = primaryStage;
          this.rootLayout = rootLayout;
          this.appController = appController;
      }
  
      public void changeScene(String scene){
          try {
              Parent parentPane = FXMLLoader.load(getClass().getResource(scene));
              primaryStage.getScene().setRoot(parentPane);
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
  }
  
  
  public class SubController implements Initializable {
  
      private MainModel model;
  
      @Override
      public void initialize(URL url, ResourceBundle rb) {
      }    
  
      public void setModel(MainModel model){
          this.model = model;
      }    
  }
  
  
  &lt;?xml version="1.0" encoding="UTF-8"?&gt;
  
  &lt;?import javafx.scene.control.Label?&gt;
  &lt;?import javafx.scene.layout.AnchorPane?&gt;
  &lt;?import javafx.scene.layout.Pane?&gt;
  &lt;?import javafx.scene.text.Font?&gt;
  
  &lt;AnchorPane id="AnchorPane" prefHeight="524.0" prefWidth="850.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="app.SubController"&gt;
     &lt;children&gt;
        &lt;Label fx:id="lbl" layoutX="52.0" layoutY="13.0" prefHeight="38.0" prefWidth="214.0" text="just a label"&gt;
           &lt;font&gt;
              &lt;Font name="Consolas" size="24.0" /&gt;
           &lt;/font&gt;
        &lt;/Label&gt;
     &lt;/children&gt;
  &lt;/AnchorPane&gt;
  </code></pre>
  
  <p>I tried the following things to load the other controller:
  First I tried doing it the same way I am loading the <code>appController</code> (since that works), but without setting the view as the <code>scene</code>. So in the <code>initRootLayout()</code> method I simply added:</p>
  
  <pre><code>FXMLLoader subloader = new FXMLLoader();
  subloader.setLocation(getClass().getResource("subView.fxml"));
  subController = loader.&lt;SubController&gt;getController();
  </code></pre>
  
  <p>This didn't work. In fact something really weird happened. When I tried calling a method from <code>subController</code>, I got a <code>NullPointerException</code>. Debugging revealed that the <code>subController</code> is being loaded, but right after its loaded it disappears and <code>subController</code> Object is just "null". Why is that?</p>
  
  <p>The next thing I tried after reading about this approach was to add the <code>subController</code> as a <code>FXML</code> variable. In the <code>AppController</code> I added <code>@FXML private SubController subController;</code> and in the <code>AppController</code>'s <code>initialize()</code> method I tried making a call from the controller:</p>
  
  <pre><code>    @Override
      public void initialize(URL url, ResourceBundle rb) {
          subController.setModel(model);
      } 
  </code></pre>
  
  <p>In this case, I am getting a <code>NullPointerException</code>, but it is actually pointing to the line where I call <code>appController.initModel(model);</code> in the <code>App</code> class. Even though this line works fine when I am not trying to use the <code>subController</code>. 
  So, I am extremely confused and I think I need a whole new structure for this. Any kinda help would be greatly appreciated! :)</p>
  
  <p>EDIT: 
  <strong>This seems to be working</strong>: I changed the <code>changeScenes()</code> method to this:</p>
  
  <pre><code>public void changeScene(String scene){
      try {
       FXMLLoader loader = new FXMLLoader(getClass().getResource(scene));
       Parent root = (Parent) loader.load();
       subViewController = loader.getController();
       subViewController.setModel(mainModel);
       Scene newScene = new Scene(root);
       Stage newStage = new Stage();
       newStage.setScene(newScene);
       newStage.show();
    } catch (Exception e) {
       e.printStackTrace();
    }
  }
  </code></pre>