0

I have 2 controllers and 3 FXML-files.
1. Controllers:
MainController.java
In this controller i am create Stage and Scene with BorderPane. In center of BorderPane i want to change layouts(GridPane, HBox etc)

public class MainController {

    //Main BorderPane
    private BorderPane borderPane;

    @FXML
    private void initialize() {
       try {

          FXMLLoader  mainLoaderFXML = new FXMLLoader();
          mainLoaderFXML.setLocation(getClass().getResource("BaseView.fxml"));
          borderPane = (BorderPane) mainLoaderFXML.load();

          Stage mainStage = new Stage();
          mainStage.setTitle("Border Pane");

          Scene mainScene = new Scene(borderPane);
          mainStage.setScene(mainScene);

          FXMLLoader loader = new FXMLLoader();
          loader.setLocation(getClass().getResource("CenterView1.fxml"));

          //BorderPane in CenterView1.fxml          
          BorderPane centerView1 = (BorderPane) loader.load();

          borderPane.setCenter(centerView1);

          mainStage.show();


       } catch (IOException e) {
          e.printStackTrace();
       }

    }

    //Get BorderPane
    public BorderPane getBorderPane() {
         return this.borderPane;
    }

}

SecondController.java
In the SecondController i want to change Center of borderPane MainController with help radioButton.

public class SecondController {
    @FXML
    private ToggleGroup radioButtons;

    @FXML
    private void initialize() {

        radioButtons.selectedToggleProperty().addListener(new ChangeListener<Toggle>() {
            public void changed(ObservableValue<? extends Toggle> ov,
                Toggle old_toggle, Toggle new_toggle) {
                if (radioButtons.getSelectedToggle() != null) {
                    RadioButton chk = (RadioButton)new_toggle.getToggleGroup().getSelectedToggle(); 

                    switch(chk.getText()){
                        case "rbFirst": 
                            System.out.println("Default View CenterView1"); 
                            break;
                        case "rbSecond": 

                            FXMLLoader  mainLoaderFXML = new FXMLLoader();
                                mainLoaderFXML.setLocation(getClass().getResource("BaseView.fxml"));

                                MainController mainController = (MainController)mainLoaderFXML.getController();

                                //And now i want to change new FXML-file into center, but i have a NULLPointerException
                                System.out.println(mainController.getDefaultNormsLayout().setCenter("CenterView2"));
                            break;
                    }
                }
            }
        });
    }
}


2. FXML-file:
0.BaseView.fxml - base view
1. CenterView1.fxml (by default) - it's BorderPane in the center of Base View
2. CenterView2.fxml - it's DataGrid in the center of Base View

When i click on rbSecond i see NullPointerException in mainController.getDefaultNormsLayout(). I know what is it, but i don't know hot to fix it. I am use JavaFX class controller scene reference, enter link description here etc but i don't known how to it apply for my task.
Thanks!

Community
  • 1
  • 1
Tomas
  • 1,567
  • 3
  • 21
  • 38
  • The controller should be created with the view and this is not the case before the load operation if I am correct. Beside that, I would rethink your architecture. Thats not the way javafx should be used in my opinion. Edit: Keep in mind the MainController in that setup is not a singleton. – mh-dev Mar 05 '16 at 18:47
  • @mh-dev, thanks for your answer! But why my architecture don't correct? When i can read about standart project architecture with JavaFx? – Tomas Mar 05 '16 at 19:07
  • When you need a toggle behaviour create a component which does this. This style tends to be not refactoring save, since it contains string constants representing files. More problematic is the "CenterView2" thing. Additional I see potential problems with the not singleton controller, but thats my personal opinion. I use a spring based setup with a view navigation mechanic based on the controller classes instead of the fxml files. – mh-dev Mar 05 '16 at 19:18
  • @mh-dev, maybe do you have example with your method? – Tomas Mar 05 '16 at 19:23
  • Sorry that code was created in my job and so I am not allowed to make it public. For a simple spring integration see: http://stancalau.ro/javafx-and-spring/ – mh-dev Mar 05 '16 at 19:34

1 Answers1

1

Answer from my comment:

The nullpointer occures, because the controller is not initialized before the load operation of the FXMLLoader. This will create another instance of the MainController class. This will not be the same instance as the initial one, if the default JavaFX is not overwritten. See the setControllerFactory method of the FXMLLoader class. Keep in mind that it is important to not reuse the FXMLLoader class.

The following should ensure that mainController is not null anymore.

FXMLLoader  mainLoaderFXML = new FXMLLoader(); 
mainLoaderFXML.setLocation(getClass().getResource("BaseView.fxml"));
mainLoaderFXML.load();
MainController mainController =  (MainController)mainLoaderFXML.getController();

Singleton Controller

Use singleton mechanic of your choice and get the instance. If you want to control the creation of a controller classe use.

mainLoaderFxml.setControllerFactory(new Callback() {
     public Object call(Class<?> clazz) {
          return instance of your class;
     }
}
mh-dev
  • 5,264
  • 4
  • 25
  • 23
  • Yes, i know this. But i don't know how to fix it. – Tomas Mar 05 '16 at 19:26
  • added a little sample – mh-dev Mar 05 '16 at 19:33
  • I am use your example, but now i have _java.lang.ClassCastException: application.view.SecondController cannot be cast to application.view.MainController_ in _MainController mainController = (MainController)mainLoaderFXML.getController();_ ((( – Tomas Mar 05 '16 at 19:47
  • That depends on your fxml file file. Seems that the controller defined in the "BaseView.fxml" is NormsController and not MainController. – mh-dev Mar 05 '16 at 19:51
  • Than, can i delete controller from Base.fxml?? – Tomas Mar 05 '16 at 19:55
  • A JavaFx view does have a controller and its the one you define. When you do not like the controller defined its up to you to change it. But it seems that you need to read a bit about fxml basics in javafx. Since this questions do not relate to your initial problem. – mh-dev Mar 05 '16 at 19:57
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/105458/discussion-between-tomas-and-mh-dev). – Tomas Mar 05 '16 at 19:58