Is there any Date and Time picker available for ja

2020-07-02 12:21发布

I am new to Java and I have started developing applications in java using javaFx. searched a lot but couldn't find any date and time picker in javaFx. Even i tried JFxtras but its not working. By the way i am using javafx 2.2.3 and java 7. Any help would be highly appreciated.

4条回答
We Are One
2楼-- · 2020-07-02 12:24

I find it most convenient to enter the time via the keyboard instead of changing it with sliders. It's quite easy to extend the included DatePicker to look like this:

DateTimePicker for JavaFX 8

I also find it annoying that the DatePicker doesn't commit the edited value in the TextField onblur, so the following code fixes that as well.

The snippet is written in Kotlin for brevety, you can easily convert it to Java via IntelliJ IDEA:

import javafx.beans.property.SimpleObjectProperty
import javafx.scene.control.DatePicker
import javafx.scene.input.KeyCode
import javafx.scene.input.KeyEvent
import javafx.scene.input.MouseEvent
import javafx.util.StringConverter
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.format.DateTimeFormatter

class DateTimePicker(val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")) : DatePicker() {
    private var dateTimeValue = SimpleObjectProperty<LocalDateTime>(LocalDateTime.now())

    init {
        converter = object : StringConverter<LocalDate>() {
            override fun toString(value: LocalDate?): String {
                return if (dateTimeValue.get() != null) dateTimeValue.get().format(formatter) else ""
            }

            override fun fromString(value: String?): LocalDate? {
                if (value == null) {
                    dateTimeValue.set(null)
                    return null
                }

                dateTimeValue.set(LocalDateTime.parse(value, formatter))
                return dateTimeValue.get().toLocalDate()
            }
        }

        // Syncronize changes to the underlying date value back to the dateTimeValue
        valueProperty().addListener { observable, old, new ->
            if (new == null) {
                dateTimeValue.set(null)
            } else {
                if (dateTimeValue.get() == null) {
                    dateTimeValue.set(LocalDateTime.of(new, LocalTime.now()))
                } else {
                    val time = dateTimeValue.get().toLocalTime()
                    dateTimeValue.set(LocalDateTime.of(new, time))
                }
            }
        }

        // Syncronize changes to dateTimeValue back to the underlying date value
        dateTimeValue.addListener { observable, old, new ->
            valueProperty().set(new?.toLocalDate())
        }

        // Persist changes onblur
        editor.focusedProperty().addListener { observable, old, new ->
            if (!new)
                simulateEnterPressed()
        }

    }

    private fun simulateEnterPressed() =
        editor.fireEvent(KeyEvent(editor, editor, KeyEvent.KEY_PRESSED, null, null, KeyCode.ENTER, false, false, false, false))

    fun dateTimeValueProperty() = dateTimeValue;
}

Bind your LocalDateTime property to the dateTimeValueProperty.

查看更多
啃猪蹄的小仙女
3楼-- · 2020-07-02 12:25

Slightly "improved" (at least for my needs) version that works with NullableTimeStamp... in order to be able to, well, null it (for ease with MySQL)...

Dunno if this can help anyone but here it is:

NullableTimeStamp:

public class NullableTimestamp extends Timestamp {

    public NullableTimestamp() {
        super(0L);
    }
    public NullableTimestamp(long value) {
        super(value);
    }

    @Override
    public String toString() {
        return this.getTime() > 0L ? super.toString() : "";
    }

    public static NullableTimestamp valueOf(LocalDateTime localDateTime) {
        return new NullableTimestamp(Timestamp.valueOf(localDateTime).getTime());
    }
}

and DateTimePicker:

public class DateTimePicker extends DatePicker {
    public static final String DefaultFormat = "yyyy-MM-dd HH:mm";

    private DateTimeFormatter formatter;
    private ObjectProperty<LocalDateTime> dateTimeValue = new SimpleObjectProperty<>(LocalDateTime.now());
    private ObjectProperty<String> format = new SimpleObjectProperty<String>() {
        public void set(String newValue) {
            super.set(newValue);
            formatter = DateTimeFormatter.ofPattern(newValue);
        }
    };

    public DateTimePicker() {
        getStyleClass().add("datetime-picker");
        setFormat(DefaultFormat);
        setConverter(new InternalConverter());

        // Syncronize changes to the underlying date value back to the dateTimeValue
        valueProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue == null) {
                dateTimeValue.set(null);
            } else {
                if (dateTimeValue.get() == null) {
                    dateTimeValue.set(LocalDateTime.of(newValue, LocalTime.now()));
                } else {
                    LocalTime time = dateTimeValue.get().toLocalTime();
                    dateTimeValue.set(LocalDateTime.of(newValue, time));
                }
            }
        });

        // Syncronize changes to dateTimeValue back to the underlying date value
        dateTimeValue.addListener((observable, oldValue, newValue) -> {
            setValue(newValue == null ? null : newValue.toLocalDate());
        });

        // Persist changes onblur
        getEditor().focusedProperty().addListener((observable, oldValue, newValue) -> {
            if (!newValue)
                simulateEnterPressed();
        });

    }

    private void simulateEnterPressed() {
        getEditor().fireEvent(new KeyEvent(getEditor(), getEditor(), KeyEvent.KEY_PRESSED, null, null, KeyCode.ENTER, false, false, false, false));
    }

    public LocalDateTime getDateTimeValue() {
        return dateTimeValue.get();
    }

    public void setDateTimeValue(LocalDateTime dateTimeValue) {
        if(dateTimeValue.isAfter(LocalDateTime.of(1971, 6, 30, 12, 00)))
            this.dateTimeValue.set(dateTimeValue);
        else
            this.dateTimeValue.set(null);
    }

    public ObjectProperty<LocalDateTime> dateTimeValueProperty() {
        return dateTimeValue;
    }

    public String getFormat() {
        return format.get();
    }

    public ObjectProperty<String> formatProperty() {
        return format;
    }

    public void setFormat(String format) {
        this.format.set(format);
    }

class InternalConverter extends StringConverter<LocalDate> {
    public String toString(LocalDate object) {

        LocalDateTime value = getDateTimeValue();
        return (value != null) ? value.format(formatter) : "";
    }

    public LocalDate fromString(String value) {
        if (value == null) {
            dateTimeValue.set(null);
            return null;
        }

        dateTimeValue.set(LocalDateTime.parse(value, formatter));
        return dateTimeValue.get().toLocalDate();
        }
    }
}

It basically masks the 0L Timestamp value as if it was NULL... hope this can help cheers

查看更多
看我几分像从前
4楼-- · 2020-07-02 12:38

Here is a Java version of the DateTimePicker control above, slightly improved.

This code is now part of TornadoFX Controls and you can have a look at the latest version of DateTimePicker.java in the GitHub Repo. The control is available in Maven Central as well under these coordinates:

<dependency>
    <groupId>no.tornado</groupId>
    <artifactId>tornadofx-controls</artifactId>
    <version>1.0.3</version>
</dependency>

The implementation right now:

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.control.DatePicker;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.util.StringConverter;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

/**
 * A DateTimePicker with configurable datetime format where both date and time can be changed
 * via the text field and the date can additionally be changed via the JavaFX default date picker.
 */
@SuppressWarnings("unused")
public class DateTimePicker extends DatePicker {
    public static final String DefaultFormat = "yyyy-MM-dd HH:mm";

    private DateTimeFormatter formatter;
    private ObjectProperty<LocalDateTime> dateTimeValue = new SimpleObjectProperty<>(LocalDateTime.now());
    private ObjectProperty<String> format = new SimpleObjectProperty<String>() {
        public void set(String newValue) {
            super.set(newValue);
            formatter = DateTimeFormatter.ofPattern(newValue);
        }
    };

    public DateTimePicker() {
        getStyleClass().add("datetime-picker");
        setFormat(DefaultFormat);
        setConverter(new InternalConverter());

        // Syncronize changes to the underlying date value back to the dateTimeValue
        valueProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue == null) {
                dateTimeValue.set(null);
            } else {
                if (dateTimeValue.get() == null) {
                    dateTimeValue.set(LocalDateTime.of(newValue, LocalTime.now()));
                } else {
                    LocalTime time = dateTimeValue.get().toLocalTime();
                    dateTimeValue.set(LocalDateTime.of(newValue, time));
                }
            }
        });

        // Syncronize changes to dateTimeValue back to the underlying date value
        dateTimeValue.addListener((observable, oldValue, newValue) -> {
            setValue(newValue == null ? null : newValue.toLocalDate());
        });

        // Persist changes onblur
        getEditor().focusedProperty().addListener((observable, oldValue, newValue) -> {
            if (!newValue)
                simulateEnterPressed();
        });

    }

    private void simulateEnterPressed() {
        getEditor().fireEvent(new KeyEvent(getEditor(), getEditor(), KeyEvent.KEY_PRESSED, null, null, KeyCode.ENTER, false, false, false, false));
    }

    public LocalDateTime getDateTimeValue() {
        return dateTimeValue.get();
    }

    public void setDateTimeValue(LocalDateTime dateTimeValue) {
        this.dateTimeValue.set(dateTimeValue);
    }

    public ObjectProperty<LocalDateTime> dateTimeValueProperty() {
        return dateTimeValue;
    }

    public String getFormat() {
        return format.get();
    }

    public ObjectProperty<String> formatProperty() {
        return format;
    }

    public void setFormat(String format) {
        this.format.set(format);
    }

    class InternalConverter extends StringConverter<LocalDate> {
        public String toString(LocalDate object) {
            LocalDateTime value = getDateTimeValue();
            return (value != null) ? value.format(formatter) : "";
        }

        public LocalDate fromString(String value) {
            if (value == null) {
                dateTimeValue.set(null);
                return null;
            }

            dateTimeValue.set(LocalDateTime.parse(value, formatter));
            return dateTimeValue.get().toLocalDate();
        }
    }
}

The dateTimeValue property contains the value with time, and the valueProperty contains only the date value.

I have not added tests for this component yet, so the implementation might change, check GitHub for the latest version.

查看更多
Rolldiameter
5楼-- · 2020-07-02 12:40

JFXtras project has a working version for JavaFX 2.2. Look for CalendarPicker, CalendarTimePicker, ... at the repo, under the 2.2 branch.

You can test it by downloading the lastest release (2.2-r6-SNAPSHOT) from jfxtras.org.

This short snippet will create a calendar for picking both date and time:

@Override
public void start(Stage primaryStage) {
    CalendarPicker dateTime = new CalendarPicker();
    dateTime.withCalendar(Calendar.getInstance());
    dateTime.withShowTime(Boolean.TRUE);
    dateTime.withLocale(Locale.ENGLISH);
    dateTime.calendarProperty().addListener(new ChangeListener<Calendar>() {

        @Override
        public void changed(ObservableValue<? extends Calendar> ov, Calendar t, Calendar t1) {
            System.out.println("Selected date: "+t1.getTime().toString());
        }
    });
    StackPane root = new StackPane();
    root.getChildren().add(dateTime);

    Scene scene = new Scene(root, 300, 250);
    primaryStage.setTitle("Date & Time from JFXtras 2.2");
    primaryStage.setScene(scene);
    primaryStage.show();
}

Date and Time

查看更多
登录 后发表回答