gpt4 book ai didi

java - JSpinner.DateEditor 必须包括年份,即使开始和结束是同一年

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:19:23 26 4
gpt4 key购买 nike

我有一个使用 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 年底,则微调器不会让您的用户滚动到 1970 年的 1 月1971 年(相反它可能会跳回到 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 源代码中四处寻找,我建议您查看 InternationalFormatter(DateFormatter 的父类(super class))的公共(public)方法 stringToValue(String text)

关于java - JSpinner.DateEditor 必须包括年份,即使开始和结束是同一年,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3875215/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com