JSpinner.DateEditor必须包括年份,即使开始和结束是同一年 [英] JSpinner.DateEditor must include year even though start and end is the same year

查看:112
本文介绍了JSpinner.DateEditor必须包括年份,即使开始和结束是同一年的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用SpinnerDateModel的JSpinner,它的开头是2010年1月1日00:00:00.000结束日期是2010年1月1日00:12:34.217。我希望我的JSpinner.DateEditor使用格式HH:mm:ss.SSS但旋转器不会使用此格式旋转。只有在将yyyy添加到格式时才会旋转。我该如何解决这个问题?

I have a JSpinner using a SpinnerDateModel which has a start at Jan 1, 2010 00:00:00.000 the end date is Jan 1, 2010 00:12:34.217. I would like my JSpinner.DateEditor to use the format HH:mm:ss.SSS but the spinner doesn't spin with this format. It only spins when "yyyy" is added to the format. How can I get around this?

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年。当您尝试旋转时,这会导致微调器始终返回超出范围的错误。

After a good bit of digging around in the JRE source I discovered the the spinner is backed by a text value instead of a true date. When you hit the up and down spin buttons, the value is parsed and then compared to your min and max values. Because your format does not have a year the dates are parsed with the year always being 1970 which is year offset 0 from the epoch. This causes the spinner to always return an out of range error when you try to spin it.

最快的解决方案是简单地使用1970作为你的年份不是2010年。但是,如果你的初始日期是1970年底,那么微调器就不会让你的用户翻到1971年1月(相反它可能会跳回到1970年初)。

The quickest solution is to simply use 1970 as your year instead of 2010. However, if your initial date is at the end of 1970 the spinner won't let your users roll over into January of 1971 (instead it may jump back to the beginning of 1970).

其他解决方案可以容纳跨越日历年边界的日期。但是,它并不那么简单(或漂亮)。在JRE中,当DateFormatter解析日期字符串时,它使用单个String参数构造函数动态地实例化一个类。该字符串是微调器的日期。默认情况下,此类是Date或其子类。我们可以让格式化程序实例化我们自己的Date类,它修复了执行任何日期比较之前的年份。

The other solution can accomodate dates that span calendar year boundaries. However, it is not as simple (or pretty). In the JRE when the DateFormatter parses the date string, it instantiates a class dynamically using a single String parameter constructor. This string is the date from the spinner. By default, this class is either Date or some subclass of it. We can have the formatter instantiate our own Date class which fixes the year before any date comparisons are performed.

添加年份的日期类:

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!






丑陋,但确实有效。


Ugly, but it works.

此外,如果你想在JRE源代码中寻找,我建议你看一下InternationalFormatter的公共方法 stringToValue(String text) (DateFormatter的超类)。

Also, If you want to poke around in the JRE source I suggest looking at the public method stringToValue(String text) of InternationalFormatter (superclass of DateFormatter).

这篇关于JSpinner.DateEditor必须包括年份,即使开始和结束是同一年的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆