【问题标题】:Set step for a DateEditor in a JSpinner在 JSpinner 中为 DateEditor 设置步骤
【发布时间】:2012-05-08 08:19:12
【问题描述】:

如何为JSpinner 指定一个step? (例如 10 分钟而不是 1 分钟)

有一个模型允许为数字选择步长

SpinnerNumberModel(value, min, max, step); 

但是如何设置日期呢?

这段代码

JSpinner timeSpinner = new JSpinner( new SpinnerDateModel() );
DateEditor timeEditor = new DateEditor(timeSpinner, "HH:mm:ss");
timeSpinner.setEditor(timeEditor);
timeSpinner.setValue(new Date()); // will only show the current time

(来自这个答案Is there any good and free Date AND Time Picker available for Java Swing?

仅允许编辑时间,但步长始终为 1 小时、1 分钟或 1 秒,具体取决于是否指定了“HH”、“HH:mm”或“HH:mm:ss”。


有没有什么简单的方法可以让 min、max 和 step 保持几分钟?

谢谢

【问题讨论】:

  • 好吧,Date 可以使用getTime() 轻松转换为long,您可以在milliseconds 中以时间增量添加登录,然后将其转换回Date在印刷时..

标签: java jspinner


【解决方案1】:

使用DateEditor.getModel() 获取提供setStartsetEndsetCalendarFieldSpinnerDateModel

【讨论】:

  • “calendarField 属性的值必须是指定日历中的字段的 java.util.Calendar 常量之一”,然后不可能分配 10 分钟的步骤,因为 TEN_MINUTES 不是日历中的常量
【解决方案2】:

SpinnerDateModel的代码中可以看到:

public Object getNextValue() {
    Calendar cal = Calendar.getInstance(); //Current date.
    cal.setTime(value.getTime()); //Set the date to the current value of the model.
    cal.add(calendarField, 1); //Increment the date by 1 unit of the selected calendar field (e.g. 1 month).
    Date next = cal.getTime(); //Convert back to Date Object.
    return ((end == null) || (end.compareTo(next) >= 0)) ? next : null;
}

public Object getPreviousValue() {
    Calendar cal = Calendar.getInstance(); //Current date.
    cal.setTime(value.getTime()); //Set the date to the current value of the model.
    cal.add(calendarField, -1); //Decrement the date by 1 unit of the selected calendar field (e.g. 1 month).
    Date prev = cal.getTime(); //Convert back to Date Object.
    return ((start == null) || (start.compareTo(prev) <= 0)) ? prev : null;
}

它适用于添加或减去指定日历字段的 1 个单位。
您想将此数字 1 自定义为其他内容。
所以我在这里看到两个选项:

  1. 重新实现AbstractSpinnerModel。只需复制粘贴SpinnerDateModel(它并不大),然后引入您的整数字段“step”,而不是数字 1,只需将“step”放入 getNextgetPrevious
  2. 实现SpinnerDateModel,它也可以在内部使用SpinnerDateModel。它会小很多,但我猜有点hackish。

遵循这样一个SpinnerDateModel的代码(案例2):

import java.awt.GridLayout;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;

public class MultiStepDateSpinner extends JPanel {
    private static class StepperSpinnerDateModel extends SpinnerDateModel {
        private final SpinnerDateModel internal; //We let the internal SpinnerDateModel do the work for us.
        private final int step; //The number of steps to increment and decrement per click.
        private Object currentValue; //Needed to get restored each time getPreviousValue and getNextValue is called.

        private StepperSpinnerDateModel(final Date value, final Comparable start, final Comparable end, final int calendarField, final int step) {
            internal = new SpinnerDateModel(value, start, end, calendarField);
            if (step <= 0)
                throw new IllegalArgumentException("Non positive step.");
            this.step = step;
            currentValue = internal.getValue();
        }

        private StepperSpinnerDateModel(final int step) {
            this(new Date(), null, null, Calendar.DAY_OF_MONTH, step);
        }

        @Override
        public Object getValue() {
            return currentValue;
        }

        @Override
        public void setValue(final Object value) {
            internal.setValue(value);
            currentValue = value;
            fireStateChanged(); //Important step for the spinner to get updated each time the model's value changes.
        }

        @Override
        public Object getNextValue() {
            Object next = null;
            for (int i=0; i<step; ++i) { //Calculate step next values:
                next = internal.getNextValue();
                internal.setValue(next); //We have to set the next value internally, in order to recalculate the next-next value in the next loop.
            }
            internal.setValue(currentValue); //Restore current value.
            return next;
        }

        @Override
        public Object getPreviousValue() {
            Object prev = null;
            for (int i=0; i<step; ++i) { //Calculate step previous values:
                prev = internal.getPreviousValue();
                internal.setValue(prev); //We have to set the previous value internally, in order to recalculate the previous-previous value in the next loop.
            }
            internal.setValue(currentValue); //Restore current value.
            return prev;
        }
    }

    private MultiStepDateSpinner() {
        super(new GridLayout(0, 1));

        //Increment and decrement by 4 minutes each step.
        //The null values indicate there shall be no minimum nor maximum date.
        //The current value is set to the current date.
        final JSpinner spinner = new JSpinner(new StepperSpinnerDateModel(new Date(), null, null, Calendar.MINUTE, 4));

        final JButton getValueButton = new JButton("Get value");
        getValueButton.addActionListener(e -> {
            JOptionPane.showMessageDialog(null, spinner.getValue(), "Got value", JOptionPane.PLAIN_MESSAGE);
        });

        add(spinner);
        add(getValueButton);
    }

    public static void main(final String[] args) {
        final JFrame frame = new JFrame("Frame");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new MultiStepDateSpinner());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

上面的示例代码是可运行的,所以你可以在实践中看到它。

为什么不让它成为AbstractSpinnerModel 而不是SpinnerDateModel?因为我们需要将其标识为SpinnerDateModel 的实例,所以JSpinner 在内部默认为编辑器分配DateEditor
即使您扩展AbstractSpinnerModel 并为微调器提供DateEditor,您也会收到一个异常,抱怨模型不是SpinnerDateModel

在我看来,最简洁的方法是重新实现 AbstractSpinnerModel 并在需要时复制粘贴 SpinnerDateModel 的代码(不大)并引入您认为的任何字段。

【讨论】:

    【解决方案3】:
    Incrementa JSpinnerDateEditor_15_+_15_minutos
        Calendar Horacalendario = Calendar.getInstance();
        Horacalendario.setTime(cita_hora.getDate());
        Date HoraParaCita = Horacalendario.getTime();//para asignar luego del incremento de 15 formato date()'
        int minutos = Horacalendario.get(Calendar.MINUTE);
        Horacalendario.set(Horacalendario.get(Calendar.YEAR), Horacalendario.get(Calendar.MONTH),
                Horacalendario.get(Calendar.DATE), Horacalendario.get(Calendar.HOUR), 0);//hago cero los minutos
        if (minutos >= 1 & minutos <= 14) {
            Horacalendario.add(Calendar.MINUTE, 15); //minutos A Sumar 
            HoraParaCita = Horacalendario.getTime();
            cita_hora.setDate(HoraParaCita);
        }
        if (minutos >= 16 & minutos <= 29) {
            Horacalendario.add(Calendar.MINUTE, 30);
            HoraParaCita = Horacalendario.getTime();
            cita_hora.setDate(HoraParaCita);
        }
        if (minutos >= 31 & minutos <= 44) {
            Horacalendario.add(Calendar.MINUTE, 45);
            HoraParaCita = Horacalendario.getTime();
            cita_hora.setDate(HoraParaCita);
        }
        if (minutos >= 46 & minutos <= 59) {
            Horacalendario.set(Horacalendario.get(Calendar.YEAR), Horacalendario.get(Calendar.MONTH),
                    Horacalendario.get(Calendar.DATE), Horacalendario.get(Calendar.HOUR), 0);//hago cero los minutos
            HoraParaCita = Horacalendario.getTime();
            cita_hora.setDate(HoraParaCita);
        }
    

    【讨论】:

    • 仅代码答案不是很有帮助。尝试添加解释如何解决问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-13
    • 2013-12-25
    • 1970-01-01
    相关资源
    最近更新 更多