JieFormattedDateBox 是一個繼承 JFormattedTextField 並實作 SpinnerModel 的日期時間輸入元件,支援自訂格式、遮罩輸入、Spinner 整合、游標位置感知的增減邏輯。本文解析其核心設計與完整原始碼。
// 日期時間完整格式
JieFormattedDateBox box = new JieFormattedDateBox("yyyy年MM月dd日HH點mm分ss秒");
// 僅時間
JieFormattedDateBox timeBox = new JieFormattedDateBox("HH:mm:ss");
// 整合 JSpinner
JSpinner spinner = new JSpinner();
JieFormattedDateBox fdb = new JieFormattedDateBox("yyyy-MM-dd");
spinner.setModel(fdb);
spinner.setEditor(fdb);
SimpleDateFormat 與 MaskFormatter 雙重保障。DocumentListener 監聽輸入變化,呼叫 checkTime() 解析並更新內部 Timestamp。FocusListener 在失去焦點時強制重置為合法值。getNextValue()/getPreviousValue() 根據游標位置決定增減單位(年/月/日/時/分/秒)。setValue() 保留 caretPosition,提升編輯體驗。靜態陣列定義單位對應毫秒值:
static String[] alias = {"yyyy","MM","dd","HH","hh","mm","ss"};
static long[] times = {0, 0, 86400000, 3600000, 3600000, 60000, 1000};
testAlias(format, caret, index) 判斷游標落在哪個時間單位區間,getIncrease/Decrease 計算跨月/跨年邊界時的精確毫秒差值(含月份天數變化處理)。
package org.jie.ui.formattedbox;
public class JieFormattedDateBox extends JFormattedTextField implements SpinnerModel {
private String format;
private SimpleDateFormat timeFormat;
private Timestamp time;
// 建構子:初始化格式、遮罩、DocumentListener、FocusListener
public JieFormattedDateBox(String format) { ... }
// 即時驗證邏輯
void checkTime() { ... }
// SpinnerModel 介面實作
public Object getValue() { return getText(); }
public void setValue(Object value) { ... }
public Object getNextValue() { ... }
public Object getPreviousValue() { ... }
public void addChangeListener(ChangeListener l) {}
public void removeChangeListener(ChangeListener l) {}
// 靜態工具方法
static boolean testAlias(String format, int caret, int index) { ... }
static long getIncrease(int caret, String format, Timestamp time) { ... }
static long getDecrease(int caret, String format, Timestamp time) { ... }
public static String replace(String src, String replaceSrc, String replaceWith) { ... }
}
JSpinner 提供視覺化增減按鈕的場合。