JFormattedTextField失去焦点后日期变更问题求助
解决JFormattedTextField日期字段失去焦点后日期变更的问题
嘿,我之前在做桌面数据库项目的时候也踩过JFormattedTextField日期组件的这个坑——失去焦点后日期莫名其妙变了,太闹心了!结合我的经验,给你几个能解决问题的方案:
1. 关闭日期格式化的宽松模式(最关键)
默认的日期格式化器会开启宽松模式,它会自动把不合法的日期(比如2月30日、13月1日)调整成“合法”的日期,甚至在输入不完整时自动补全年份/月份,这就是导致日期偷偷变更的核心原因。
解决方法是手动创建SimpleDateFormat并关闭宽松模式:
// 明确指定日期格式,比如dd/MM/yyyy(日/月/年) SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); dateFormat.setLenient(false); // 关闭宽松模式,拒绝任何不合法的日期 DateFormatter dateFormatter = new DateFormatter(dateFormat);
2. 配置字段的焦点丢失行为
JFormattedTextField默认的焦点丢失行为可能会在输入无效时自动回滚或修改值,我们可以手动设置成更可控的行为:
DefaultFormatterFactory dateFactory = new DefaultFormatterFactory(dateFormatter); JFormattedTextField dateField = new JFormattedTextField(dateFactory); // 设置失去焦点时的行为:COMMIT = 提交当前有效输入;COMMIT_OR_REVERT = 无效则回滚到之前的值 dateField.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT);
推荐用COMMIT_OR_REVERT,既保证合法输入会被保存,又不会在输入无效时偷偷修改日期。
3. 添加手动验证,拦截无效输入
可以给日期字段添加焦点监听器,在失去焦点时手动验证输入,一旦发现无效就提示用户并把焦点拉回来:
dateField.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { try { // 手动提交编辑,触发格式化验证 dateField.commitEdit(); } catch (ParseException ex) { // 输入无效时的处理逻辑 JOptionPane.showMessageDialog(null, "请输入有效的日期,格式为:dd/MM/yyyy"); // 让焦点回到日期字段,方便用户修改 dateField.requestFocusInWindow(); } } });
4. Java 8+ 推荐用DateTimeFormatter(线程安全)
如果你用的是Java 8及以上版本,建议用DateTimeFormatter代替SimpleDateFormat(它是线程安全的,功能更强大),同样要开启严格解析模式:
// 严格模式下,必须完全匹配格式,拒绝任何不合法的日期 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/uuuu") .withResolverStyle(ResolverStyle.STRICT); // 适配成DateFormatter供JFormattedTextField使用 DateFormatter dateFormatter = new DateFormatter(new Format() { @Override public String format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { LocalDate date = (LocalDate) obj; return dtf.format(date); } @Override public Object parseObject(String source, ParsePosition pos) { try { LocalDate date = LocalDate.parse(source, dtf); pos.setIndex(source.length()); return Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()); } catch (DateTimeParseException ex) { pos.setErrorIndex(pos.getIndex()); return null; } } });
把这些步骤结合起来,你的日期字段应该就不会在失去焦点后乱改日期了!
内容的提问来源于stack exchange,提问作者lordzwieback
相关产品推荐
相关产品推荐

