Java Swing實現(xiàn)自定義日期時間選擇器組件
一、背景
Swing 原生沒有好用的日期時間選擇器組件。如果想讓用戶選擇日期,通常只能用手寫文本框加格式校驗,代碼繁瑣且體驗一般。下拉選擇年月日的方式也需要自己實現(xiàn),維護成本高。
所以封裝了一個工具類 DatePickerUtils,統(tǒng)一管理常用配置,一行代碼搞定日期時間選擇器。
項目中選擇了開源庫 LGoodDatePicker,功能完整、文檔清晰。這個庫支持日期選擇、時間選擇、日期時間組合選擇,還內(nèi)置了日期范圍限制等常用功能。
二、依賴說明
本工具類基于 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 工具類),可按需替換或自行實現(xiàn)判空邏輯。
三、核心方法一覽
| 方法 | 返回類型 | 說明 |
|---|---|---|
| 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 對象 |
四、源碼實現(xiàn)
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. 創(chuàng)建日期選擇器(默認 yyyy-MM-dd):
* DatePicker datePicker = DatePickerUtils.datePicker();
* 2. 創(chuàng)建時間選擇器(精確到分鐘):
* DateTimePicker picker = DatePickerUtils.minute();
* 3. 獲取 Date 類型值:
* Date date = DatePickerUtils.getDate(datePicker);
*/
public class DatePickerUtils {
/**
* 創(chuàng)建日期選擇器(默認格式 yyyy-MM-dd,包含之前日期)
* @return 日期選擇器
*/
public static DatePicker datePicker() {
return datePicker(true);
}
/**
* 創(chuàng)建日期選擇器(可限制只能選今天及之后)
* @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;
}
/**
* 創(chuàng)建日期選擇器(自定義格式)
* @param pattern 日期格式,如 "yyyy-MM-dd"
* @return 日期選擇器
*/
public static DatePicker datePicker(String pattern) {
return datePicker(pattern, true);
}
/**
* 創(chuàng)建日期選擇器(完整參數(shù))
* @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;
}
/**
* 創(chuàng)建時間選擇器(精確到小時)
* @return 日期時間選擇器
*/
public static DateTimePicker hour() {
return picker("HH");
}
/**
* 創(chuàng)建時間選擇器(精確到分鐘,包含之前時間)
* @return 日期時間選擇器
*/
public static DateTimePicker minute() {
return minute(true);
}
/**
* 創(chuàng)建時間選擇器(精確到分鐘)
* @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;
}
/**
* 創(chuàng)建時間選擇器(精確到秒,包含之前時間)
* @return 日期時間選擇器
*/
public static DateTimePicker second() {
return second(true);
}
/**
* 創(chuàng)建時間選擇器(精確到秒)
* @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 的值(轉(zhuǎn)為 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());
}
// ==================== 私有方法 ====================
/**
* 創(chuàng)建日期選擇器配置
* @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;
}
/**
* 創(chuàng)建日期時間選擇器
* @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 基礎(chǔ)日期選擇
// 創(chuàng)建日期選擇器(默認格式 yyyy-MM-dd,可選之前日期)
DatePicker datePicker = DatePickerUtils.datePicker();
// 創(chuàng)建日期選擇器(只能選擇今天及之后)
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("獲取結(jié)果");
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);
// 結(jié)果展示
gbc.gridy = 3;
resultLabel = new JLabel("請選擇日期時間");
add(resultLabel, gbc);
}
}
六、注意事項
- 依賴管理:需要引入 LGoodDatePicker 庫,版本推薦 11.2.1 或更高
- 日期范圍限制:通過 before 參數(shù)控制是否允許選擇之前日期,false 表示只能選擇今天及之后
- 時間間隔:分鐘/秒的間隔參數(shù)范圍是 1-60,超出會自動限制到邊界值
- Hutool 依賴:StrUtil.isBlank() 方法可替換為 pattern == null || pattern.trim().isEmpty()
- 時區(qū)問題:getDate() 方法使用系統(tǒng)默認時區(qū),如需指定時區(qū)可自行修改
- 鍵盤編輯:默認禁用了鍵盤編輯(setAllowKeyboardEditing(false)),避免用戶手動輸入非法格式
七、小結(jié)
DatePickerUtils 封裝了 LGoodDatePicker 的常用配置,提供了簡潔的工廠方法,一行代碼即可創(chuàng)建日期或日期時間選擇器。 核心優(yōu)勢:
- 開箱即用,無需重復配置日期格式、時間格式、時間間隔
- 支持日期范圍限制(只能選未來/可選過去)
- 支持分鐘/秒的自定義間隔
- 提供 DatePicker → java.util.Date 的轉(zhuǎn)換方法
到此這篇關(guān)于Java Swing實現(xiàn)自定義日期時間選擇器組件的文章就介紹到這了,更多相關(guān)Java Swing日期時間選擇器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java數(shù)字轉(zhuǎn)中文大寫工具類詳細代碼(拿去即用)
最近項目中用到金額轉(zhuǎn)大寫的地方,索性給大家總結(jié)下,這篇文章主要給大家介紹了關(guān)于Java數(shù)字轉(zhuǎn)中文大寫工具類的相關(guān)資料,文中給出了詳細的代碼示例,需要的朋友可以參考下2024-05-05
Apache Commons Math3探索之多項式曲線擬合實現(xiàn)代碼
這篇文章主要介紹了Apache Commons Math3探索之多項式曲線擬合實現(xiàn)代碼,小編覺得挺不錯的,這里分享給大家,供需要的朋友參考。2017-10-10
java8 如何實現(xiàn)分組計算數(shù)量和計算總數(shù)
這篇文章主要介紹了java8 如何實現(xiàn)分組計算數(shù)量和計算總數(shù)的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07

