正如您在以下代码中看到的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 自定义为其他内容。
所以我在这里看到两个选项:
- 重新实现
AbstractSpinnerModel
. 只需复制粘贴SpinnerDateModel
(它并不大),然后例如引入整数字段“step”,而不是数字 1,只需将“step”放入getNext
and中getPrevious
。
- 实现 a
SpinnerDateModel
,它也可以在内部与 a 一起使用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
为编辑器分配 a。
即使您扩展AbstractSpinnerModel
并为微调器提供 a DateEditor
,您也会收到一个异常,抱怨模型不是 a SpinnerDateModel
。
但在我看来,最干净的方法是重新实现AbstractSpinnerModel
并复制粘贴SpinnerDateModel
如果需要的代码(不是很大),并引入您认为的任何字段。