Highlight Days in JavaFX DatePicker
javafxToday I had the requirement to implement a highlighting of some days in the JavaFX DatePicker
. As I haven't found an
existing blog post or tutorial that describes this topic I will provide a short example here.
Similar to other JavaFX controls like ListView
or TreeTable
the DatePicker
can be configured with a CellFactory.
In this cellFactory you can configure the styling of individual cells.
The basic code looks like this:
DatePicker datePicker = new DatePicker();
datePicker.setDayCellFactory(new Callback<DatePicker, DateCell>() {
@Override
public DateCell call(DatePicker param) {
return new DateCell() {
@Override
public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
}
}
}
})
JavaFX will reuse existing DateCell
instances when the visible viewport is changed when the user switches between
pages in the DatePicker. This way JavaFX saves resources and minimizes new instances as much as possible.
To reuse existing cells we need to override the updateItem
method which will get the new LocalDate
object as
parameter. Inside this method we can now check if this day should get a special styling.
In my example I will highlight the holidays (in Saxony, Germany) with a special color.
The first step is to define the list of LocalDate
s that we are interested in. Then we can check the given LocalDate
value in the updateItem
method.
List<LocalDate> holidays = new ArrayList<>();
holidays.add(LocalDate.of(2018, Month.JANUARY, 1));
holidays.add(LocalDate.of(2018, Month.MARCH, 3));
holidays.add(LocalDate.of(2018, Month.APRIL, 2));
holidays.add(LocalDate.of(2018, Month.MAY, 1));
holidays.add(LocalDate.of(2018, Month.MAY,10));
holidays.add(LocalDate.of(2018, Month.MAY,21));
holidays.add(LocalDate.of(2018, Month.OCTOBER,3));
holidays.add(LocalDate.of(2018, Month.OCTOBER,31));
holidays.add(LocalDate.of(2018, Month.NOVEMBER,21));
holidays.add(LocalDate.of(2018, Month.DECEMBER,25));
holidays.add(LocalDate.of(2018, Month.DECEMBER,26));
DatePicker datePicker = new DatePicker();
datePicker.setDayCellFactory(new Callback<DatePicker, DateCell>() {
@Override
public DateCell call(DatePicker param) {
return new DateCell(){
@Override
public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
if (!empty && item != null) {
if(holidays.contains(item)) {
this.setStyle("-fx-background-color: pink");
}
}
}
};
}
});
The result looks like this:
An even better approach is to use a CSS file to define the styling. In the cell-factory we then only set a CSS class that is referred to in the CSS file. The code of the cell-factory could look like this:
datePicker.setDayCellFactory(new Callback<DatePicker, DateCell>() {
@Override
public DateCell call(DatePicker param) {
return new DateCell(){
@Override
public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
if (!empty && item != null) {
if(holidays.contains(item)) {
this.getStyleClass().add("holiday");
}
}
}
};
}
});
To write the CSS code we can use the modena.css as a reference point. The code looks like this:
.date-picker-popup > * > .date-cell.holiday {
-fx-background-color: pink;
}