javaFx 是不是有可用的日期和时间选择器?
Posted
技术标签:
【中文标题】javaFx 是不是有可用的日期和时间选择器?【英文标题】:Is there any Date and Time picker available for javaFx?javaFx 是否有可用的日期和时间选择器? 【发布时间】:2015-04-14 02:40:03 【问题描述】:我是 Java 新手,我已经开始使用 javaFx 在 Java 中开发应用程序。搜索了很多,但在 javaFx 中找不到任何日期和时间选择器。即使我尝试了 JFxtras,但它不起作用。顺便说一句,我正在使用 javafx 2.2.3 和 java 7。任何帮助将不胜感激。
【问题讨论】:
有机会升级到 Java 8 吗? 不,先生。我只需要解决这个问题。 您可以使用date picker created by Christian Schudt。教程可以关注Marco Jakob blog 请注意,Java SE 7 计划在今年春天停产。建议届时升级到 Java SE 8 或与 Oracle 签订支持合同。 @SorcyCat:在 SE 7 中没有时间选择器。如果你是 java 8,你可以使用 jfxtras。 【参考方案1】:这是上面 DateTimePicker 控件的 Java 版本,略有改进。
此代码现在是 TornadoFX Controls 的一部分,您可以在 GitHub 存储库中查看最新版本的 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 以获取最新版本。
【讨论】:
【参考方案2】:JFXtras 项目有一个适用于 JavaFX 2.2 的工作版本。在 2.2 分支下的 repo 中查找 CalendarPicker
、CalendarTimePicker
、...。
您可以通过从jfxtras.org 下载最新版本 (2.2-r6-SNAPSHOT) 来测试它。
这个简短的 sn-p 将创建一个用于选择日期和时间的日历:
@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();
【讨论】:
【参考方案3】:我发现通过键盘输入时间而不是使用滑块更改时间最方便。将包含的 DatePicker 扩展为如下所示非常容易:
我还发现 DatePicker 没有在 TextField onblur 中提交编辑后的值很烦人,所以下面的代码也修复了这个问题。
为了简洁起见,sn-p 是用 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。
【讨论】:
你能把它作为java代码提供吗? (这是一个 java 问题,intelliJ 不是免费软件) 好的,我会把它转换成Java代码并贴在这里。不过,IntelliJ 社区版是完全免费的。 这仅适用于本地日期,但不适用于本地时间。我注意到造成这种情况的原因是您没有将本地时间坚持到 value 属性。当您从 value 属性推送更改时,本地时间不会分配给 datetimevalue 属性。【参考方案4】:与 NullableTimeStamp 一起使用的略微“改进”(至少满足我的需要)版本...以便能够将其归零(以便于使用 mysql)...
不知道这是否可以帮助任何人,但这里是:
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());
和日期时间选择器:
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...希望这可以帮助欢呼
【讨论】:
以上是关于javaFx 是不是有可用的日期和时间选择器?的主要内容,如果未能解决你的问题,请参考以下文章
我的 Bootstrap-4 日期时间选择器无法在 Internet Explorer 上运行?是不是有任何适用于 Bootstrap 4.0 的日期时间选择器?