Java Swing实现自定义日期时间选择器组件

 更新时间:2026年05月17日 10:45:34   作者:RainCity  
Swing 原生没有好用的日期时间选择器组件,如果想让用户选择日期,通常只能用手写文本框加格式校验,代码繁琐且体验一般,下面小编就和大家分享一下Java Swing实现自定义日期时间选择器的相关方法吧

一、背景

Swing 原生没有好用的日期时间选择器组件。如果想让用户选择日期,通常只能用手写文本框加格式校验,代码繁琐且体验一般。下拉选择年月日的方式也需要自己实现,维护成本高。

所以封装了一个工具类 DatePickerUtils,统一管理常用配置,一行代码搞定日期时间选择器。

项目中选择了开源库 LGoodDatePicker,功能完整、文档清晰。这个库支持日期选择、时间选择、日期时间组合选择,还内置了日期范围限制等常用功能。

二、依赖说明

本工具类基于 com.github.lgooddatepicker 库,需要在项目中引入:

Maven:

<dependency>
    <groupId>com.github.lgooddatepicker</groupId>
    <artifactId>LGoodDatePicker</artifactId>
    <version>11.2.1</version>
</dependency>

Gradle:

implementation 'com.github.lgooddatepicker:LGoodDatePicker:11.2.1'

同时使用了 cn.hutool.core.util.StrUtil(Hutool 工具类),可按需替换或自行实现判空逻辑。

三、核心方法一览

方法返回类型说明
datePicker()DatePicker日期选择器,yyyy-MM-dd,包含之前日期
datePicker(boolean before)DatePicker日期选择器,可控制是否包含之前日期
datePicker(String pattern)DatePicker日期选择器,自定义格式,包含之前日期
datePicker(String pattern, boolean before)DatePicker日期选择器,自定义格式,可控制是否包含之前日期
hour()DateTimePicker日期时间选择器,至小时,yyyy-MM-dd HH
minute()DateTimePicker日期时间选择器,至分钟,间隔5分钟,包含之前
minute(boolean before)DateTimePicker日期时间选择器,至分钟,间隔5分钟,可控制是否包含之前
minute(TimePickerSettings.TimeIncrement timeIncrement)DateTimePicker日期时间选择器,至分钟,自定义时间间隔(5/10/15/20/30/60),包含之前
minute(TimePickerSettings.TimeIncrement timeIncrement, boolean before)DateTimePicker日期时间选择器,至分钟,自定义时间间隔,可控制是否包含之前
minute(int interval)DateTimePicker日期时间选择器,至分钟,自定义间隔(1-60),包含之前
minute(int interval, boolean before)DateTimePicker日期时间选择器,至分钟,自定义间隔(1-60),可控制是否包含之前
second()DateTimePicker日期时间选择器,至秒,间隔1秒,包含之前
second(boolean before)DateTimePicker日期时间选择器,至秒,间隔1秒,可控制是否包含之前
second(int interval)DateTimePicker日期时间选择器,至秒,自定义间隔(1-60),包含之前
second(int interval, boolean before)DateTimePicker日期时间选择器,至秒,自定义间隔(1-60),可控制是否包含之前
getDate(DatePicker datePicker)Date从 DatePicker 获取 java.util.Date 对象

四、源码实现

import cn.hutool.core.util.StrUtil;
import com.github.lgooddatepicker.components.DatePicker;
import com.github.lgooddatepicker.components.DatePickerSettings;
import com.github.lgooddatepicker.components.DateTimePicker;
import com.github.lgooddatepicker.components.TimePickerSettings;

import java.awt.*;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 日期时间选择器工具类
 * 基于 LGoodDatePicker 开源库封装
 *  * 使用示例:
 * 1. 创建日期选择器(默认 yyyy-MM-dd):
 *    DatePicker datePicker = DatePickerUtils.datePicker();
 * 2. 创建时间选择器(精确到分钟):
 *    DateTimePicker picker = DatePickerUtils.minute();
 * 3. 获取 Date 类型值:
 *    Date date = DatePickerUtils.getDate(datePicker);
 */
public class DatePickerUtils {

    /**
     * 创建日期选择器(默认格式 yyyy-MM-dd,包含之前日期)
     * @return 日期选择器
     */
    public static DatePicker datePicker() {
        return datePicker(true);
    }

    /**
     * 创建日期选择器(可限制只能选今天及之后)
     * @param before 是否包含之前的日期(true=包含,false=只能选今天及之后)
     * @return 日期选择器
     */
    public static DatePicker datePicker(boolean before) {
        DatePicker datePicker = datePicker("yyyy-MM-dd");
        if (!before) {
            datePicker.getSettings().setDateRangeLimits(LocalDate.now(), null);
        }
        return datePicker;
    }

    /**
     * 创建日期选择器(自定义格式)
     * @param pattern 日期格式,如 "yyyy-MM-dd"
     * @return 日期选择器
     */
    public static DatePicker datePicker(String pattern) {
        return datePicker(pattern, true);
    }

    /**
     * 创建日期选择器(完整参数)
     * @param pattern 日期格式
     * @param before 是否包含之前的日期
     * @return 日期选择器
     */
    public static DatePicker datePicker(String pattern, boolean before) {
        DatePicker datePicker = new DatePicker();
        datePicker.setSettings(datePickerSettings(pattern));
        if (!before) {
            datePicker.getSettings().setDateRangeLimits(LocalDate.now(), null);
        }
        return datePicker;
    }

    /**
     * 创建时间选择器(精确到小时)
     * @return 日期时间选择器
     */
    public static DateTimePicker hour() {
        return picker("HH");
    }

    /**
     * 创建时间选择器(精确到分钟,包含之前时间)
     * @return 日期时间选择器
     */
    public static DateTimePicker minute() {
        return minute(true);
    }

    /**
     * 创建时间选择器(精确到分钟)
     * @param before 是否包含之前的日期和时间
     * @return 日期时间选择器
     */
    public static DateTimePicker minute(boolean before) {
        DateTimePicker dateTimePicker = picker("HH:mm");
        if (!before) {
            dateTimePicker.datePicker.getSettings().setDateRangeLimits(LocalDate.now(), null);
        }
        dateTimePicker.timePicker.getSettings().generatePotentialMenuTimes(
            TimePickerSettings.TimeIncrement.FiveMinutes, 
            before ? null : LocalTime.now(), 
            null
        );
        return dateTimePicker;
    }

    /**
     * 创建时间选择器(精确到秒,包含之前时间)
     * @return 日期时间选择器
     */
    public static DateTimePicker second() {
        return second(true);
    }

    /**
     * 创建时间选择器(精确到秒)
     * @param before 是否包含之前的日期和时间
     * @return 日期时间选择器
     */
    public static DateTimePicker second(boolean before) {
        DateTimePicker dateTimePicker = picker("HH:mm:ss");
        if (!before) {
            dateTimePicker.datePicker.getSettings().setDateRangeLimits(LocalDate.now(), null);
        }
        dateTimePicker.timePicker.getSettings().generatePotentialMenuTimes(
            before ? LocalTime.MIN : LocalTime.now(), 
            null
        );
        return dateTimePicker;
    }

    /**
     * 获取 DatePicker 的值(转为 java.util.Date)
     * @param datePicker 日期选择器
     * @return Date 对象,未选择时返回 null
     */
    public static Date getDate(DatePicker datePicker) {
        if (null == datePicker) return null;
        LocalDate localDate = datePicker.getDate();
        if (null == localDate) return null;
        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    // ==================== 私有方法 ====================

    /**
     * 创建日期选择器配置
     * @param pattern 日期格式
     * @return 配置对象
     */
    private static DatePickerSettings datePickerSettings(String pattern) {
        pattern = StrUtil.isBlank(pattern) ? "yyyy-MM-dd" : pattern;
        DatePickerSettings settings = new DatePickerSettings();
        settings.setFormatForDatesCommonEra(DateTimeFormatter.ofPattern(pattern));
        settings.setFormatForDatesBeforeCommonEra(DateTimeFormatter.ofPattern(pattern));
        settings.setAllowKeyboardEditing(false);
        Font font = new Font("Microsoft YaHei", Font.PLAIN, 14);
        settings.setFontCalendarWeekdayLabels(font);
        return settings;
    }

    /**
     * 创建日期时间选择器
     * @param timeFormat 时间格式(HH、HH:mm、HH:mm:ss)
     * @return 日期时间选择器
     */
    private static DateTimePicker picker(String timeFormat) {
        DatePickerSettings dateSettings = datePickerSettings("yyyy-MM-dd");
        TimePickerSettings timeSettings = new TimePickerSettings();
        timeSettings.setFormatForMenuTimes(DateTimeFormatter.ofPattern(timeFormat));
        timeSettings.setFormatForDisplayTime(DateTimeFormatter.ofPattern(timeFormat));
        timeSettings.setAllowKeyboardEditing(false);
        timeSettings.setInitialTimeToNow();

        DateTimePicker picker = new DateTimePicker(dateSettings, timeSettings);
        picker.datePicker.setDateToToday();
        picker.timePicker.setTimeToNow();
        return picker;
    }
}

五、使用示例

5.1 基础日期选择

// 创建日期选择器(默认格式 yyyy-MM-dd,可选之前日期)
DatePicker datePicker = DatePickerUtils.datePicker();

// 创建日期选择器(只能选择今天及之后)
DatePicker futureDatePicker = DatePickerUtils.datePicker(false);

// 自定义日期格式
DatePicker customPicker = DatePickerUtils.datePicker("yyyy/MM/dd");

// 从 DatePicker 获取 Date 对象
Date selectedDate = DatePickerUtils.getDate(datePicker);

5.2 日期时间选择(至小时)

// 选择到小时(格式:yyyy-MM-dd HH)
DateTimePicker hourPicker = DatePickerUtils.hour();

5.3 日期时间选择(至分钟)

// 默认:间隔5分钟,可选之前日期时间
DateTimePicker minutePicker = DatePickerUtils.minute();

// 只能选今天及之后的时间,间隔5分钟
DateTimePicker futureMinutePicker = DatePickerUtils.minute(false);

// 使用预定义间隔(FiveMinutes/TenMinutes/FifteenMinutes/TwentyMinutes/ThirtyMinutes/SixtyMinutes)
DateTimePicker customIntervalPicker = DatePickerUtils.minute(TimePickerSettings.TimeIncrement.TenMinutes);

// 自定义间隔(10分钟)
DateTimePicker intervalPicker = DatePickerUtils.minute(10);

// 自定义间隔,且只能选未来时间
DateTimePicker futureIntervalPicker = DatePickerUtils.minute(15, false);

5.4 日期时间选择(至秒)

// 默认:间隔1秒,可选之前日期时间
DateTimePicker secondPicker = DatePickerUtils.second();

// 只能选未来时间,间隔1秒
DateTimePicker futureSecondPicker = DatePickerUtils.second(false);

// 自定义间隔(5秒)
DateTimePicker intervalSecondPicker = DatePickerUtils.second(5);

5.5 完整示例:在面板中使用

public class DemoPanel extends JPanel {
    private DatePicker datePicker;
    private DateTimePicker dateTimePicker;
    private JLabel resultLabel;

    public DemoPanel() {
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(5, 5, 5, 5);
        gbc.fill = GridBagConstraints.HORIZONTAL;

        // 日期选择器
        gbc.gridx = 0;
        gbc.gridy = 0;
        add(new JLabel("选择日期:"), gbc);
        gbc.gridx = 1;
        datePicker = DatePickerUtils.datePicker();
        add(datePicker, gbc);

        // 日期时间选择器
        gbc.gridx = 0;
        gbc.gridy = 1;
        add(new JLabel("选择日期时间:"), gbc);
        gbc.gridx = 1;
        dateTimePicker = DatePickerUtils.minute();
        add(dateTimePicker, gbc);

        // 按钮
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 2;
        JButton btn = new JButton("获取结果");
        btn.addActionListener(e -> {
            String dateStr = datePicker.getDate() != null ? datePicker.getDate().toString() : "未选择";
            String timeStr = dateTimePicker.getDateTimeStrict() != null ? dateTimePicker.getDateTimeStrict().toString() : "未选择";
            resultLabel.setText("日期:" + dateStr + ",时间:" + timeStr);
        });
        add(btn, gbc);

        // 结果展示
        gbc.gridy = 3;
        resultLabel = new JLabel("请选择日期时间");
        add(resultLabel, gbc);
    }
}

六、注意事项

  • 依赖管理:需要引入 LGoodDatePicker 库,版本推荐 11.2.1 或更高
  • 日期范围限制:通过 before 参数控制是否允许选择之前日期,false 表示只能选择今天及之后
  • 时间间隔:分钟/秒的间隔参数范围是 1-60,超出会自动限制到边界值
  • Hutool 依赖:StrUtil.isBlank() 方法可替换为 pattern == null || pattern.trim().isEmpty()
  • 时区问题:getDate() 方法使用系统默认时区,如需指定时区可自行修改
  • 键盘编辑:默认禁用了键盘编辑(setAllowKeyboardEditing(false)),避免用户手动输入非法格式

七、小结

DatePickerUtils 封装了 LGoodDatePicker 的常用配置,提供了简洁的工厂方法,一行代码即可创建日期或日期时间选择器。 核心优势:

  • 开箱即用,无需重复配置日期格式、时间格式、时间间隔
  • 支持日期范围限制(只能选未来/可选过去)
  • 支持分钟/秒的自定义间隔
  • 提供 DatePicker → java.util.Date 的转换方法

到此这篇关于Java Swing实现自定义日期时间选择器组件的文章就介绍到这了,更多相关Java Swing日期时间选择器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot 快速搭建微服务框架详细教程

    Spring Boot 快速搭建微服务框架详细教程

    SpringBoot是为了简化Spring应用的创建、运行、调试、部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置。本文重点给大家介绍Spring Boot 快速搭建微服务框架详细教程,需要的的朋友参考下吧
    2017-09-09
  • java定时任务的实现方法

    java定时任务的实现方法

    java定时任务的实现方法,需要的朋友可以参考一下
    2013-03-03
  • JAVA实现亿级千万级数据顺序导出的示例代码

    JAVA实现亿级千万级数据顺序导出的示例代码

    本文主要介绍了JAVA实现亿级千万级数据顺序导出的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-08-08
  • java获取本地文件和远程文件的方式代码示例

    java获取本地文件和远程文件的方式代码示例

    这篇文章主要给大家介绍了关于java获取本地文件和远程文件的方式,我们项目开发的时候,经常会读取文件,如果文件在本服务器,则直接用new File()读取即可,但是有时候需要远程读取文件,需要的朋友可以参考下
    2023-08-08
  • Java实现优雅停止线程的有效方法详解

    Java实现优雅停止线程的有效方法详解

    这篇文章主要为大家详细如何安全有效停止 Java 线程的,确保多线程应用程序平稳运行并实现最佳资源管理,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • Java设计模式之抽象工厂模式

    Java设计模式之抽象工厂模式

    这篇文章主要为大家详细介绍了Java设计模式之抽象工厂模式的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • Java list移除元素相关操作指南

    Java list移除元素相关操作指南

    这篇文章主要给大家介绍了关于Java list移除元素相关操作的相关资料,文中介绍的方法包括增强for循环、迭代器、Stream流和removeIf()方法,同时还介绍了如何从一个列表中删除包含另一个列表元素的方法,以及如何删除指定下标位置的元素,需要的朋友可以参考下
    2024-12-12
  • Java重写equals及hashcode方法流程解析

    Java重写equals及hashcode方法流程解析

    这篇文章主要介绍了Java重写equals及hashcode方法流程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • spring mvc4.1.6 spring4.1.6 hibernate4.3.11 mysql5.5.25开发环境搭建图文教程

    spring mvc4.1.6 spring4.1.6 hibernate4.3.11 mysql5.5.25开发环境搭

    这篇文章主要介绍了spring mvc4.1.6 + spring4.1.6 + hibernate4.3.11+mysql5.5.25开发环境搭建图文教程,需要的朋友可以参考下
    2016-06-06
  • 详解Java的引用类型及使用场景

    详解Java的引用类型及使用场景

    这篇文章主要介绍了详解Java的引用类型及使用场景,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-03-03

最新评论