0

I'm creating a export dialog in JavaFX which is loaded from a .fxml file. To initialize the method I would like to use the initialize() method. However, when accessing @FXML gui elements during the initialize() call, i'm getting a NullPointerException because they are still null.

Here my code which is creating the dialog in my controller.MainController class:

        // Create dialog
        FXMLLoader loader = new FXMLLoader(this.getClass().getResource("/view/exportDialog.fxml" ));
        AnchorPane exportDialog = (AnchorPane) loader.load();
        exportController = (ExportDialogController)loader.getController();
        Stage dialogStage = new Stage();
        dialogStage.setTitle("Export...");
        dialogStage.initModality(Modality.WINDOW_MODAL);
        dialogStage.initOwner(this.stage);
        Scene scene = new Scene(exportDialog);
        dialogStage.setScene(scene);
        dialogStage.show();

And here is the controller of the export dialog which is stored in controller.ExportDialogController:

public class ExportDialogController {
    Stage stage = null;

    // GUI Elements
    @FXML
    private AnchorPane anchorPane;

    @FXML
    private ProgressBar exportProgressBar;

    @FXML
    private Label exportStatusLabel;

    @FXML
    private Button exportButton;

    public void initialize() {
        Stage stage = (Stage)exportButton.getScene().getWindow();
        stage.setOnCloseRequest(event -> close());
    }
}

Here is the code of my .fxml file which is stored in view.exportDialog:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefWidth="600.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.ExportDialogController">
   <children>
      <ProgressBar fx:id="exportProgressBar" layoutX="75.0" layoutY="155.0" prefHeight="28.0" prefWidth="450.0" progress="0.0" AnchorPane.leftAnchor="25.0" AnchorPane.rightAnchor="25.0" AnchorPane.topAnchor="50.0" />
      <Label layoutX="47.0" layoutY="42.0" prefHeight="17.0" prefWidth="218.0" text="Exporting dataset....." AnchorPane.leftAnchor="25.0" AnchorPane.topAnchor="25.0" />
      <Label fx:id="exportStatusLabel" alignment="CENTER" layoutX="286.0" layoutY="203.0" text="Export successful!" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="90.0" />
      <Button fx:id="exportButton" layoutX="261.0" layoutY="115.0" mnemonicParsing="false" onAction="#exportButtonPressed" prefHeight="25.0" prefWidth="79.0" text="Cancel" AnchorPane.bottomAnchor="25.0" AnchorPane.topAnchor="120.0" />
   </children>
</AnchorPane>

I've linked the controller in the .fxml file and I also added the fx:ids.

enter image description here

According to the documentaion of JavaFX, the gui elements should at this point already been injected.

What I'm doing wrong here?

Erik Wolf
  • 144
  • 1
  • 12
  • I don't see the relation of the two questions clearly and I never would find the other question when searching for a similar problem like mine. – Erik Wolf Jan 05 '18 at 14:10

1 Answers1

1

The initialize() method is called during the call to loader.load(). Obviously, and necessarily, the export button is not part of a scene at that point (that doesn't happen until you call new Scene(exportDialog)), so exportButton.getScene() returns null and exportButton.getScene().getWindow() throws a null pointer exception.

Since the stage is managed from the code in the MainController class, you should register listeners with it there:

    // Create dialog
    FXMLLoader loader = new FXMLLoader(this.getClass().getResource("/view/exportDialog.fxml" ));
    AnchorPane exportDialog = (AnchorPane) loader.load();
    exportController = (ExportDialogController)loader.getController();
    Stage dialogStage = new Stage();

    dialogStage.setOnCloseRequest(event -> exportController.close());

    dialogStage.setTitle("Export...");
    dialogStage.initModality(Modality.WINDOW_MODAL);
    dialogStage.initOwner(this.stage);
    Scene scene = new Scene(exportDialog);
    dialogStage.setScene(scene);
    dialogStage.show();

and remove the code from the initialize() method in ExportDialogController.

James_D
  • 201,275
  • 16
  • 291
  • 322