24

I have the main application class that does the following just fine:

   @Override
   public void start(Stage primaryStage) {
      try {
         FXMLLoader loader = new FXMLLoader(getClass().getResource(
               "RecordScreen.fxml"));
         Parent root = (Parent) loader.load();
         Scene newScene = new Scene(root);
         Stage newStage = new Stage();
         newStage.setScene(newScene);
         newStage.show();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

It launches a table view that displays people. I select a person, hit the edit button, and try to launch a window that will let me edit them.

   @FXML
   public void editPerson() {
      try {
         FXMLLoader loader = new FXMLLoader(getClass().getResource(
               "PersonEditor.fxml"));
         PersonEditorCtrl ctrl = loader.getController();
         ctrl.init(table.getSelectionModel().getSelectedItem());
         Parent root = (Parent) loader.load();
         Scene newScene = new Scene(root);
         Stage newStage = new Stage();
         newStage.setScene(newScene);
         newStage.show();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

The problem is, getController is returning null. I have been following this pattern for the past 2 weeks with no problems whatsoever. What am I doing wrong now? These untraceable bugs are aggravating!!!

Here are my two fxmls:

The screen with tableview:

<AnchorPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="application.RecordsCtrl">
  <!-- TODO Add Nodes -->
  <children>
    <VBox id="VBox" alignment="CENTER" spacing="0.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
      <children>
        <TableView fx:id="table" prefHeight="-1.0" prefWidth="-1.0">
          <columns>
            <TableColumn prefWidth="75.0" text="Name" fx:id="nameCol" />
            <TableColumn prefWidth="75.0" text="Age" fx:id="ageCol" />
          </columns>
        </TableView>
        <Button mnemonicParsing="false" onAction="#editPerson" text="Edit" />
      </children>
    </VBox>
  </children>
</AnchorPane>

The person editor:

<AnchorPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="application.PersonEditorCtrl">
  <!-- TODO Add Nodes -->
  <children>
    <VBox layoutX="0.0" layoutY="0.0" prefHeight="-1.0" prefWidth="-1.0">
      <children>
        <TextField fx:id="nameField" prefWidth="200.0" />
        <TextField fx:id="ageField" prefWidth="200.0" />
        <Button mnemonicParsing="false" text="Button" />
      </children>
    </VBox>
  </children>
</AnchorPane>
Toni_Entranced
  • 969
  • 2
  • 12
  • 29

2 Answers2

68

Change this

@FXML
   public void editPerson() {
      try {
         FXMLLoader loader = new FXMLLoader(getClass().getResource(
               "PersonEditor.fxml"));
         PersonEditorCtrl ctrl = loader.getController();
         ctrl.init(table.getSelectionModel().getSelectedItem());
         Parent root = (Parent) loader.load();
         Scene newScene = new Scene(root);
         Stage newStage = new Stage();
         newStage.setScene(newScene);
         newStage.show();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

To that:

@FXML
   public void editPerson() {
      try {
         FXMLLoader loader = new FXMLLoader(getClass().getResource(
               "PersonEditor.fxml"));
         Parent root = (Parent) loader.load();
         PersonEditorCtrl ctrl = loader.getController();
         ctrl.init(table.getSelectionModel().getSelectedItem());

         Scene newScene = new Scene(root);
         Stage newStage = new Stage();
         newStage.setScene(newScene);
         newStage.show();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

You first have to run loader.load() then you can get the Controller.

Patrick

Patrick
  • 4,532
  • 2
  • 26
  • 32
  • For sure. By the way, can you point me in the right direction? My tableview does not reflect the changes made to the people on the list. When I edit them again with the edit button, the changes are there. It's just that the TableView doesn't reflect them. – Toni_Entranced May 04 '14 at 20:57
  • 1
    Actually never mind, I think I've figure it out. The observable list is causing issues for a lot of people. :\ – Toni_Entranced May 04 '14 at 21:04
  • @Luc The difference is, that the op has to call the load() method on his FXMLoader first, then he can call getController() Method. – Patrick Jan 29 '15 at 08:20
2

In your scene builder, you need to make sure that you have explicitly stated the fx:controller attribute.

To do this:

  1. Open your desired FXML file in Scenebuilder.
  2. Click on the controller drop down.
  3. Select the controller class.

If you do not specify the fx:controller it will return null.

  • while a missing controller attribute _could_ be a problem, in this question it's _not_ the case :) - both fxml files shown in the question have the fx:controller set. See the accepted answer for the cause of the null. – kleopatra Feb 27 '23 at 13:38