I have multiple DatePickers in my project and I want to make it so that the user cannot edit the text field and so they can't select a date before todays date on all of them.
I know how to do this to individual DatePickers but I want a way to apply this to all of them.
Here's the code I would use for them individually:
DatePicker datePicker = new DatePicker();
datePicker.getEditor().setDisable(true);
datePicker.getEditor().setOpacity(1);
datePicker.setDayCellFactory(param -> new DateCell() {
@Override
public void updateItem(LocalDate date, boolean empty) {
super.updateItem(date, empty);
setDisable(empty || date.compareTo(LocalDate.now()) < 0 );
}
});
Edit: As James_D commented I could just put these commands in a method which is the solution I used. Using a builder for this is also interesting, thanks for the detailed answer.
Use some kind of creational pattern, e.g. a builder pattern.
Create an implementation of Builder<DatePicker>
:
import java.time.LocalDate;
import javafx.scene.control.DateCell;
import javafx.scene.control.DatePicker;
import javafx.util.Builder;
public class DatePickerBuilder implements Builder<DatePicker>{
public DatePicker build() {
DatePicker datePicker = new DatePicker();
datePicker.getEditor().setDisable(true);
datePicker.getEditor().setOpacity(1);
datePicker.setDayCellFactory(param -> new DateCell() {
@Override
public void updateItem(LocalDate date, boolean empty) {
super.updateItem(date, empty);
setDisable(empty || date.compareTo(LocalDate.now()) < 0 );
}
});
return datePicker ;
}
}
If you're creating your DatePicker
s in Java code, you can simply instantiate a DatePickerBuilder
and use it:
private final DatePickerBuilder datePickerBuilder = new DatePickerBuilder();
// ...
// any time you need a `DatePicker` do
DatePicker datePicker = datePickerBuilder.build();
If you're using FXML, you can wrap the DatePickerBuilder
in a custom BuilderFactory
:
import javafx.fxml.JavaFXBuilderFactory;
import javafx.scene.control.DatePicker;
import javafx.util.Builder;
import javafx.util.BuilderFactory;
public class DatePickerBuilderFactory implements BuilderFactory {
private final BuilderFactory defaultFactory ;
private final DatePickerBuilder builder ;
public DatePickerBuilderFactory() {
defaultFactory = new JavaFXBuilderFactory();
builder = new DatePickerBuilder();
}
@Override
public Builder<?> getBuilder(Class<?> type) {
if (type == DatePicker.class) {
return builder;
} else return defaultFactory.getBuilder(type) ;
}
}
which you can then supply to your FXMLLoader
:
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("path/to/fxml"));
fxmlLoader.setBuilderFactory(new DatePickerBuilderFactory());
Parent root = fxmlLoader.load();
Deprecation note:
The individual Builder
classes defined in JavaFX version 2.0 were deprecated in version 8.0 due to an implementation error, and removed in version 9 as there was no clean way to fix that error.
However, the BuilderFactory
and Builder
interfaces are still supported and used by the FXMLLoader
, so this code is still supported.