【发布时间】:2021-11-11 06:39:49
【问题描述】:
我有一个本质上是 JFormattedTextField 的东西,它使用 DateFormatter,从用户控制的语言环境中获取其格式 环境。下面的代码试图在没有大量专有代码的情况下重现这一点。 (对于我在顶级 Swing 方面的粗鲁尝试,我深表歉意……)
我的问题是,如果用户选择了具有两位数年份的语言环境,则无法输入“错误”世纪的日期。例如,如果我运行下面的程序并将年份编辑为 2047 并单击“确定”,程序将打印 1947 年的日期。
原因似乎是 JFormattedTextField likes to "normalize" 它的数据通过文本表示来回传递。一种解决方法是使用测试往返的方法覆盖 commitEdit(),如果结果破坏了年份,则用硬编码的 YYYY-MM-DD 替换格式。不过,这似乎有点笨拙。有没有更好的方法,除了要求用户选择一个理智的语言环境或为这个特定字段硬连接格式? (我知道有多种方法可以选择哪个 100 年窗口是正确的,但这仍然将我限制在 100 年窗口)。
import javax.swing.*;
import javax.swing.text.DateFormatter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.Locale;
public class Main {
private static void createAndShowGUI() {
JFrame frame = new JFrame("HelloWorldSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
var gbl = new GridBagLayout();
frame.setLayout(gbl);
final Container contentPane = frame.getContentPane();
Date date = new Date();
JFormattedTextField dateField = new JFormattedTextField(date);
dateField.setFormatterFactory(new JFormattedTextField.AbstractFormatterFactory() {
@Override
public JFormattedTextField.AbstractFormatter getFormatter(JFormattedTextField tf) {
return new DateFormatter(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.GERMANY));
}
});
contentPane.add(dateField);
JButton button = new JButton("Ok");
contentPane.add(button);
button.addActionListener((ActionEvent e) -> {
try {
dateField.commitEdit();
} catch (ParseException ex) {
ex.printStackTrace();
}
System.out.println(dateField.getValue());
});
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(Main::createAndShowGUI);
}
}
【问题讨论】:
-
有什么理由不使用 Swing 日期选择器(如 sourceforge.net/projects/jdatepicker)?
-
@PeterMmm 没有好的理由。不好的原因是,这都是内部应用程序框架的一部分,离开 JFormattedTextField 需要的更改比我目前关心的要多。 :)
-
如何用两位数的日期表示 100 多年?您可以做的最好的事情是为每个日期字段类型创建适当的滑动窗口。生日可以是当年 - 120,当年 - 21;交易日期可以是当年 - 1、当年 + 99。以此类推。
-
@camickr 我也这么认为,但显然有人忘了告诉德国人......
-
java.util日期时间 API 及其格式化 APISimpleDateFormat已过时且容易出错。建议完全停止使用,改用modern Date-Time API。
标签: java swing date dateformatter jformattedtextfield