Reputation: 752
Here is my code
@FXML
public ScrollPane mainScrollPane;
@FXML
public Label dateScrollerLabel;
@FXML
public HBox calendarContainer;
int x = 5;
@Override
public void start(Stage primaryStage) throws Exception {
scene = JavaFXUtils.createScene(1000, 600, "Main.fxml", this);
primaryStage.setScene(scene);
primaryStage.getIcons().add(new Image(Main.class.getResourceAsStream("/assets/resources/icon/icon_256.png")));
primaryStage.setTitle("HWP");
primaryStage.show();
//*****//
scene.addEventHandler(KeyEvent.KEY_PRESSED, this::keyPressed);
}
public void initialize() {
System.out.println(x); // not null
System.out.println(calendarContainer); // not null
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer); // no nullpointer exception
}
private void keyPressed(KeyEvent keyEvent) {
switch (keyEvent.getCode()) {
case A:
System.out.println(x); // not null
System.out.println(calendarContainer); // null
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer); // nullpointer exception
break;
}
}
I am able to run the following line without any errors in the initialize()
method:
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer);
However, when I run the same exact code afterward, in the keyPressed()
method, there is a nullpointer exception thrown. It seems as if calendarContainer
became null at some point between initialize()
and keyPressed
. I checked my code and at no point in my program do I change the value of calendarContainer
or re-assign it, it is only created in the FXML file.
<HBox fx:id="calendarContainer" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" styleClass="calendarContainer" />
Why does the FXML object get deleted (maybe a trigger-happy garbage collecter?) but the int does not?
Upvotes: 0
Views: 105
Reputation: 209653
Don't use the Application
class as the controller class: it makes it too difficult to keep track of which fields are initialized in which instances of the class.
Why does the FXML object get deleted
It doesn't.
Fields annotated @FXML
are only initialized in the controller. When you load the FXML file, the FXMLLoader
creates an instance of the class specified by the fx:controller
attribute, creates the objects corresponding to the elements in the FXML, and then sets the fields in the controller to the objects it created. Finally, it calls initialize()
on the controller.
So in this case, calendarContainer
is initialized in the controller (which is why you see a non-null value in your initialize()
method), but it is never initialized in the instance of the Application
class, on which start()
is called. So it doesn't suddenly become null at some point: it was always null.
You should create a separate class for the controller:
public class Controller {
@FXML
private ScrollPane mainScrollPane;
@FXML
private Label dateScrollerLabel;
@FXML
private HBox calendarContainer;
public void initialize() {
System.out.println(x); // not null
System.out.println(calendarContainer); // not null
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer); // no nullpointer exception
}
public void keyPressed(KeyEvent keyEvent) {
switch (keyEvent.getCode()) {
case A:
System.out.println(x); // not null
System.out.println(calendarContainer); // null
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer); // nullpointer exception
break;
}
}
}
(and update the fx:controller
attribute in the FXML file).
Now you Application
class can do:
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
// Not sure what this does, but you probably can't use it without some
// modification.
// scene = JavaFXUtils.createScene(1000, 600, "Main.fxml", this);
// assuming path is correct:
FXMLLoader loader = new FXMLLoader(getClass().getResource("Main.fxml"));
Scene scene = new Scene(loader.load(), 1000, 600);
Controller controller = loader.getController();
scene.addEventHandler(KeyEvent.KEY_PRESSED, controller::keyPressed);
primaryStage.setScene(scene);
primaryStage.getIcons().add(new Image(Main.class.getResourceAsStream("/assets/resources/icon/icon_256.png")));
primaryStage.setTitle("HWP");
primaryStage.show();
}
}
Upvotes: 2