Is there any implementation of Date Picker and Time Picker into the default JavaFX 8 package that I can use without using third party solutions?
DatePicker
Yes, Java 8 has a DatePicker:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.DatePicker;
import javafx.stage.Stage;
import java.time.LocalDate;
public class PickerDemo extends Application {
@Override public void start(Stage stage) {
final DatePicker datePicker = new DatePicker(LocalDate.now());
datePicker.setOnAction(event -> {
LocalDate date = datePicker.getValue();
System.out.println("Selected date: " + date);
});
stage.setScene(
new Scene(datePicker)
);
stage.show();
}
public static void main(String[] args) { launch(args); }
}
TimePicker
No, Java 8 does not have a TimePicker.
There is a TimePicker in jfxtras (source here).
Given that Java 8 already has a DatePicker, the addition of a TimePicker might be an appropriate feature request, you could make.
If you do not want to display calendar in popup. Here is a solution which uses internal CalendarPickerContent class.
DatePickerSkin skin = new DatePickerSkin(new DatePicker());
Node calendarControl = skin.getPopupContent();
here is my try based on @javaLearner answer:
DateTimePicker.java:
package test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Skin;
import javafx.util.StringConverter;
public class DateTimePicker extends DatePicker{
private ObjectProperty<LocalTime> timeValue = new SimpleObjectProperty<>();
private ObjectProperty<ZonedDateTime> dateTimeValue;
public DateTimePicker(){
super();
setValue(LocalDate.now());
setTimeValue(LocalTime.now());
setConverter(new StringConverter<LocalDate>() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HH:mm:ssZ");
@Override
public String toString ( LocalDate object ) {
return dateTimeValue.get().format(formatter);
}
@Override
public LocalDate fromString ( String string ) {
return LocalDate.parse(string, formatter);
}
});
}
@Override
protected Skin<?> createDefaultSkin () {
return new DateTimePickerSkin(this);
}
public LocalTime getTimeValue(){
return timeValue.get();
}
void setTimeValue(LocalTime timeValue){
this.timeValue.set(timeValue);
}
public ObjectProperty<LocalTime> timeValueProperty(){
return timeValue;
}
public ZonedDateTime getDateTimeValue() {
return dateTimeValueProperty().get();
}
public void setDateTimeValue (ZonedDateTime dateTimeValue) {
dateTimeValueProperty().set(dateTimeValue);
}
public ObjectProperty<ZonedDateTime> dateTimeValueProperty(){
if (dateTimeValue == null){
dateTimeValue = new SimpleObjectProperty<>(ZonedDateTime.of(LocalDateTime.of(this.getValue(), timeValue.get()), ZoneId.systemDefault()));
timeValue.addListener(t -> {
dateTimeValue.set(ZonedDateTime.of(LocalDateTime.of(this.getValue(), timeValue.get()), ZoneId.systemDefault()));
});
valueProperty().addListener(t -> {
dateTimeValue.set(ZonedDateTime.of(LocalDateTime.of(this.getValue(), timeValue.get()), ZoneId.systemDefault()));
});
}
return dateTimeValue;
}
}
DateTimePickerSkin.java:
package test;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.HBox;
import com.sun.javafx.scene.control.skin.DatePickerContent;
import com.sun.javafx.scene.control.skin.DatePickerSkin;
public class DateTimePickerSkin extends DatePickerSkin {
private DateTimePicker datePicker;
private DatePickerContent ret;
public DateTimePickerSkin(DateTimePicker datePicker){
super(datePicker);
this.datePicker = datePicker;
}
@Override
public Node getPopupContent() {
if (ret == null){
ret = (DatePickerContent) super.getPopupContent();
Slider hours = new Slider(0, 23, (datePicker.getTimeValue() != null ? datePicker.getTimeValue().getMinute() : 0));
Label hoursValue = new Label("Hours: " + (datePicker.getTimeValue() != null ? datePicker.getTimeValue().getHour() : "") + " ");
Slider minutes = new Slider(0, 59, (datePicker.getTimeValue() != null ? datePicker.getTimeValue().getMinute() : 0));
Label minutesValue = new Label("Minutes: " + (datePicker.getTimeValue() != null ? datePicker.getTimeValue().getMinute() : "") + " ");
Slider seconds = new Slider(0, 59, (datePicker.getTimeValue() != null ? datePicker.getTimeValue().getSecond() : 0));
Label secondsValue = new Label("Seconds: " + (datePicker.getTimeValue() != null ? datePicker.getTimeValue().getSecond() : "") + " ");
ret.getChildren().addAll(new HBox(hoursValue, hours), new HBox(minutesValue, minutes), new HBox(secondsValue, seconds));
hours.valueProperty().addListener((observable, oldValue, newValue) -> {
datePicker.setTimeValue(datePicker.getTimeValue().withHour(newValue.intValue()));
hoursValue.setText("Hours: " + String.format("%02d", datePicker.getTimeValue().getHour()) + " ");
});
minutes.valueProperty().addListener((observable, oldValue, newValue) -> {
datePicker.setTimeValue(datePicker.getTimeValue().withMinute(newValue.intValue()));
minutesValue.setText("Minutes: " + String.format("%02d", datePicker.getTimeValue().getMinute()) + " ");
});
seconds.valueProperty().addListener((observable, oldValue, newValue) -> {
datePicker.setTimeValue(datePicker.getTimeValue().withSecond(newValue.intValue()));
secondsValue.setText("Seconds: " + String.format("%02d", datePicker.getTimeValue().getSecond()) + " ");
});
}
return ret;
}
}
usage:
Main.java:
public class Main extends Application{
@Override
public void start ( Stage primaryStage ) {
VBox vBox = new VBox();
Scene s = new Scene(new ScrollPane(vBox), 600, 400);
DateTimePicker d = new DateTimePicker();
// Date only
d.valueProperty().addListener(t -> System.out.println(t));
// Time only
d.timeValueProperty().addListener(t -> System.out.println(t));
// DateAndTime
d.dateTimeValueProperty().addListener(t -> System.out.println(t));
vBox.getChildren().add(d);
primaryStage.setScene(s);
primaryStage.show();
}
public static void main ( String[] args ) {
launch(args);
}
}
there is still the StringConverter job to be done, but it's quite usable even like this. hope it helps someone.
PS: this was tested with jdk8u40, and it uses classes from the com.sun package (DatePickerContent/DatePickerSkin) which are not public API and might change in the future, but common, even if they do, how hard is it to adapt the above code !? :)
edit: added a StringConverter for iso8601 format and added a ZonedDateTime property for a cleaner usage (can swapped with a LocalDateTime if you don't need the Zone information)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With