Issue
I am working on a project that involves using JavaFX date picker to pick a date then do some actions based on the date.
Here is the code that is related to the date picker.
public class DatepickerController {
@FXML private DatePicker datepicker;
@FXML
public void getHolidays(ActionEvent e) {
datepicker.setOnAction(event -> {
LocalDate pickedDate = datepicker.getValue();
int month = pickedDate.getMonthValue();
int year = pickedDate.getYear();
int day = pickedDate.getDayOfMonth();
// If this date has a holiday on it, add the date to the holiday list.
});
datepicker.setDayCellFactory(new Callback<>() {
@Override
public DateCell call(DatePicker param) {
return new DateCell() {
@Override
public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
// Set cells that have holiday to a different colour
}
};
}
});
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.ProgressIndicator?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Text?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="somethingsomething.Controller.DatepickerController">
<DatePicker fx:id="calendar" layoutX="46.0" layoutY="97.0" onAction="#getHolidays" promptText="Pick a Date" />
</AnchorPane>
However every time I run the code, I get nothing for the first pick; instead I got these error messages.
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Cannot invoke "javafx.scene.control.PopupControl.isShowing()" because "<parameter1>" is null
at javafx.controls/com.sun.javafx.scene.control.behavior.DatePickerBehavior.onAutoHide(DatePickerBehavior.java:59)
at javafx.controls/javafx.scene.control.skin.ComboBoxPopupControl.lambda$createPopup$6(ComboBoxPopupControl.java:482)
at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3602)
at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3906)
at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1878)
at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2623)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:557)
at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:943)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:290)
at java.base/java.lang.Thread.run(Thread.java:833)
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Cannot invoke "javafx.scene.control.PopupControl.isShowing()" because "<parameter1>" is null
at javafx.controls/com.sun.javafx.scene.control.behavior.DatePickerBehavior.onAutoHide(DatePickerBehavior.java:59)
at javafx.controls/javafx.scene.control.skin.ComboBoxPopupControl.lambda$createPopup$5(ComboBoxPopupControl.java:476)
at javafx.graphics/javafx.stage.PopupWindow.doAutoHide(PopupWindow.java:862)
at javafx.graphics/javafx.stage.PopupWindow$PopupEventRedirector.handleAutoHidingEvents(PopupWindow.java:1047)
at javafx.graphics/javafx.stage.PopupWindow$PopupEventRedirector.handleRedirectedEvent(PopupWindow.java:989)
at javafx.base/com.sun.javafx.event.EventRedirector.dispatchCapturingEvent(EventRedirector.java:106)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchCapturingEvent(CompositeEventDispatcher.java:43)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:52)
at javafx.base/com.sun.javafx.event.EventRedirector.redirectEvent(EventRedirector.java:124)
at javafx.base/com.sun.javafx.event.EventRedirector.dispatchCapturingEvent(EventRedirector.java:103)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchCapturingEvent(CompositeEventDispatcher.java:43)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:52)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3897)
at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1878)
at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2623)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:557)
at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:943)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:290)
at java.base/java.lang.Thread.run(Thread.java:833)
I get the first half of the error when I take the first pick. After the first pick, the date picker calendar won't pop off, unless I click somewhere else, then it disappears, and I get second half of the error. After that, the datepicker will work properly.
Solution
Issues to Address
You have multiple problems.
- The
fx:id
name iscalendar
but@FXML
name isdatepicker
, they should be the same.- I suggest
datePicker
to follow standard camel case naming conventions.
- I suggest
- You add a new event handler for the date picker action every time the action is triggered. Instead you should either:
- Add the action handler in the
initialize
method and NOT in FXML OR - Add the action handler in FXML and, in the code for
getHolidays
, only provide the code which implements the action handler (don’t callsetOnAction
, the FXML loader will do that for you).
- Add the action handler in the
- You define the cell factory in the action handler. You should not do that there, you should do that in the
initialize
method.
That is what I saw from quick review of what you provided. You may have other issues.
Questions on the Solution
Answers to additional questions and topics raised in comments.
does that mean I already add the action handler in FXML?
Yes.
Read the fxml documentation to understand this. Adding an action event handler for the date picker via fxml is no different than adding an action event handler for a button.
Questions on enhancing the solution to apply MVC
I am thinking separate the cell factory part into a new class in View package because I am practicing model view separation
MVC is more complex.
Don’t try to use it until you really understand the basics where everything is in the controller. Also, only use it when you are sure you need the additional complexity (my opinion).
When you are ready, study the:
if I move it to the initialize method (still keep it in controller class), would that be considered model-view leakage
The initialize method is the correct place to set a cell factory.
You can create a separate class for the cell factory but you would instantiate an instance of that class and set it on the date picker in the initialize method.
When you instantiate the cell factory, you can pass data from the model to the cell factory in the cell factory’s constructor if needed.
If the model is set or updated after initialize is called then you can reconfigure the cell factory with new data at the time. But this is kind of beyond the scope of the original question.
If you want to have more info on applying MVC to a custom date picker cell factory, try it, and if stuck create the minimal reproducible example for that, and post a new question with the example, just specific to that topic.
Answered By - jewelsea
Answer Checked By - Robin (JavaFixing Admin)