Issue
I am creating a popup with a date picker and some other nodes. I want this date picker to show the current date when the popup is opened.
So, I set the current date in the popup controller constructor, just like I do everywhere else in my application:
public TimeAndDateController(Stage stage, Task task) {
try {
this.taskReference = task;
this.popupStage = stage;
this.datePicker = new DatePicker();
datePicker.setValue(LocalDate.now());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
I want the popup to appear when the user clicks a button in the main application window, so I add all the necessary components, and finally call showAndWait()
on the popup stage.
Event firing up the popup, somewhere in main application's controller
customTime.setOnAction(e -> Platform.runLater(() -> {
Task task = getSelectedTask();
try {
FXMLLoader loader = Utility.getFXMLLoader("fxml/timeAndDatePopup.fxml");
Stage popupStage = new Stage();
loader.setControllerFactory(c -> TimeAndDateControllerFactory(popupStage, task));
Scene scene = new Scene(loader.load());
popupStage.setScene(scene);
popupStage.showAndWait();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}));
Now the popup appears as expected without any error, but the data picker (or any other node I have there) has no value.
I don't understand why this is happening. All nodes are initialized, there are no null pointers or error messages, FXML's fine, yet I can't set a value or have any control over the nodes. I spent hours today on this, looking for answers and found nothing.
So far I have tried:
- Using a Popup class instead of a stage (as shown here).
- Setting the popup stage inside the popup controller, but that led to another oddity that prevented me from closing the popup using
stage.close()
. - Various methods for loading FXML and manually setting the controller, eg.
Solution
As the gentlemen @Slaw and @James_D in the comments rightly pointed out, the solution to the problem is the implementation of the initializable
interface, and initialize
method, in which all properties of nodes ought to be set.
This is because, as it turns out:
The FXML loader creates new nodes and if they have fx:ids it assigns the corresponding references to those nodes.
Rookie mistake.
So, in this case, the correct way to set date picker's value is as follows:
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
datePicker.setValue(LocalDate.now()); // works!
}
Answered By - 0tto
Answer Checked By - Timothy Miller (JavaFixing Admin)