我有一个使用 SpinnerDateModel 的 JSpinner,其开始日期为 2010 年 1 月 1 日 00:00:00.000,结束日期为 2010 年 1 月 1 日 00:12:34.217。我希望我的 JSpinner.DateEditor 使用格式 HH:mm:ss.SSS 但微调器不会以这种格式旋转。仅当将“yyyy”添加到格式中时才会旋转。我该如何解决这个问题?
import java.awt.GridLayout;
import java.util.*;
import javax.swing.*;
public class T extends JPanel {
public T() {
super(new GridLayout(2, 2));
init();
}
private void init() {
Calendar start = GregorianCalendar.getInstance();
Calendar end = GregorianCalendar.getInstance();
start.clear();
end.clear();
start.set(Calendar.YEAR, 2010);
end.set(Calendar.YEAR, 2010);
end.add(Calendar.HOUR_OF_DAY, 12);
SpinnerDateModel m1 =
new SpinnerDateModel(start.getTime(), start.getTime(),
end.getTime(), Calendar.MILLISECOND);
SpinnerDateModel m2 =
new SpinnerDateModel(start.getTime(), start.getTime(),
end.getTime(), Calendar.MILLISECOND);
JSpinner workingSpinner = new JSpinner(m1);
workingSpinner.setEditor(
new JSpinner.DateEditor(workingSpinner,
"yyyy HH:mm:ss.SSS"));
JSpinner notWorkingSpinner = new JSpinner(m2);
notWorkingSpinner.setEditor(
new JSpinner.DateEditor(notWorkingSpinner,
"HH:mm:ss.SSS"));
add(new JLabel("Working"));
add(workingSpinner);
add(new JLabel("!Working"));
add(notWorkingSpinner);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new T());
frame.pack();
frame.setVisible(true);
}
}
在深入研究 JRE 源代码后,我发现微调器由文本值而不是真实日期支持。当您点击向上和向下旋转按钮时,系统会解析该值,然后与最小值和最大值进行比较。由于您的格式没有年份,因此解析日期时的年份始终为 1970 年,即距纪元的偏移量为 0 的年份。这会导致当您尝试旋转旋转器时,旋转器始终返回超出范围的错误。
最快的解决方案就是简单地使用 1970 年而不是 2010 年作为您的年份。但是,如果您的初始日期是 1970 年底,则旋转器不会让您的用户滚动到 1971 年 1 月(相反,它可能会跳回 1970 年初) 。
另一种解决方案可以容纳跨越日历年边界的日期。然而,它并不那么简单(或漂亮)。在 JRE 中,当 DateFormatter 解析日期字符串时,它会使用单个 String 参数构造函数动态实例化一个类。该字符串是来自微调器的日期。默认情况下,此类是 Date 或其某个子类。我们可以让格式化程序实例化我们自己的 Date 类,该类在执行任何日期比较之前修复年份。
添加年份的日期类:
public static class DateThatAddsYear extends Date {
public DateThatAddsYear( String time ) {
super( time );
Calendar cal = GregorianCalendar.getInstance();
cal.setTime( this );
// Jump back to 2010, this needs to be implemented more thoroughly in order
// to support dates crossing calendar year boundaries
cal.set( Calendar.YEAR, 2010 );
setTime( cal.getTimeInMillis() );
}
}
使用我们的日期修复手动设置微调器:
JSpinner notWorkingSpinner = new JSpinner(m2);
JSpinner.DateEditor dateEditor = new JSpinner.DateEditor(notWorkingSpinner);
DateFormatter formatter = new DateFormatter( format );
notWorkingSpinner.setEditor(dateEditor);
dateEditor.getTextField().setFormatterFactory( new DefaultFormatterFactory( formatter ) );
formatter.setValueClass( DateThatAddsYear.class ); // Tell it to use a different value class!
丑陋,但它有效。
另外,如果您想浏览 JRE 源代码,我建议您查看 public 方法stringToValue(String text)
InternationalFormatter(DateFormatter 的超类)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)