javaFx 有可用的日期和时间选择器吗?

问题描述 投票:0回答:5

我是 Java 新手,我已经开始使用 javaFx 开发 Java 应用程序。搜索了很多,但在 javaFx 中找不到任何日期和时间选择器。即使我尝试了 JFxtras 但它不起作用。顺便说一句,我正在使用 javafx 2.2.3 和 java 7。任何帮助将不胜感激。

javafx datepicker
5个回答
14
投票

这是上面的 DateTimePicker 控件的 Java 版本,略有改进。

此代码现在是 TornadoFX Controls 的一部分,您可以在 GitHub Repo 中查看最新版本的 DateTimePicker.java。该控件也可在 Maven Central 中在以下坐标下使用:

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

目前实施情况:

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();
        }
    }
}

dateTimeValue
属性包含带有时间的值,而
valueProperty
仅包含日期值。

我还没有为此组件添加测试,因此实现可能会发生变化,请检查 GitHub 以获得最新版本。


7
投票

JFXtras 项目有 JavaFX 2.2 的工作版本。在 2.2 分支下的

repo
中查找
CalendarPicker
CalendarTimePicker、...。

您可以通过从

jfxtras.org 下载最新版本 (2.2-r6-SNAPSHOT) 来测试它。

这个简短的片段将创建一个用于选择日期和时间的日历:

@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


7
投票
我发现通过键盘输入时间最方便,而不是使用滑块更改时间。将包含的 DatePicker 扩展为如下所示非常容易:

我还发现 DatePicker 没有在 TextField onblur 中提交编辑后的值很烦人,因此下面的代码也修复了这个问题。

为简洁起见,该代码片段是用 Kotlin 编写的,您可以通过 IntelliJ IDEA 轻松将其转换为 Java:

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; }

将 LocalDateTime 属性绑定到 dateTimeValueProperty。


3
投票
稍微“改进”(至少满足我的需要)版本,与 NullableTimeStamp 一起使用...以便能够将其置空(以便于使用 MySQL)...

不知道这是否可以帮助任何人,但这里是:

可空时间戳:

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()); } }

和日期时间选择器:

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(); } } }

它基本上掩盖了 0L 时间戳值,就好像它是 NULL...希望这可以帮助欢呼


0
投票
我在这里找到了一个很好的选择器:

https://github.com/hemeroc/javafx-datetimepicker

但是这个资源在Maven和jitpack中不可用。

因此,我从这个档案库中选修了 5 门课程

https://github.com/hemeroc/javafx-datetimepicker/blob/master/src/main/java/io/github/hemeroc/javafx/datetimepicker/demo/DateTimePickerDemo.java

一切顺利。

我将 javafx 21.0.1 与 java 21 一起使用。

谢谢哈梅罗克。

© www.soinside.com 2019 - 2024. All rights reserved.