Java自定义SpinnerDateModel,仅编辑小时和分钟
我正在尝试创建一个小时和分钟的JSpinner编辑器。JSpinner非常简单Java自定义SpinnerDateModel,仅编辑小时和分钟,java,jspinner,Java,Jspinner,我正在尝试创建一个小时和分钟的JSpinner编辑器。JSpinner非常简单 JSpinner startSpinner = new JSpinner(); SpinnerWindowModel spinnerModel = new SpinnerWindowModel(); startSpinner.setModel(spinnerModel); JSpinner.DateEditor editor = new JSpinner.DateEditor(startSpinner, "HH:mm
JSpinner startSpinner = new JSpinner();
SpinnerWindowModel spinnerModel = new SpinnerWindowModel();
startSpinner.setModel(spinnerModel);
JSpinner.DateEditor editor = new JSpinner.DateEditor(startSpinner, "HH:mm");
startSpinner.setEditor(editor);
微调器窗口模型为:
public SpinnerWindowModel() {
super();
Calendar vCal = Calendar.getInstance();
vCal.set(Calendar.HOUR_OF_DAY, 8);
vCal.set(Calendar.MINUTE, 0);
vCal.set(Calendar.SECOND, 0);
setValue(vCal.getTime());
setCalendarField(Calendar.MINUTE);
vCal.set(Calendar.HOUR_OF_DAY, 6);
vCal.set(Calendar.MINUTE, 0);
vCal.set(Calendar.SECOND, 0);
setStart(vCal.getTime());
vCal.set(Calendar.HOUR_OF_DAY, 18);
vCal.set(Calendar.MINUTE, 45);
vCal.set(Calendar.SECOND, 0);
setEnd(vCal.getTime());
}
@Override
public Object getPreviousValue() {
Object obj = super.getPreviousValue();
int fld = getCalendarField();
System.out.println("GPV: " + fld);
return obj;
}
@Override
public Object getNextValue() {
Object obj = super.getNextValue();
int fld = getCalendarField();
System.out.println("GNV: " + fld);
return obj;
}
getNext/PreviousValue这两个方法当前仅用于监视调用的方法以及调用它们的字段。使用受限编辑器时,不会调用这些方法
如果我将编辑器更改为更完整的字段集,它的工作方式与我预期的一样。小时和分钟字段可编辑且正确。我需要做些什么来编辑精简编辑器吗
editor = new JSpinner.DateEditor(startSpinner, "dd/MM/yyyy HH:mm:ss.SS");
所以,当我使用你的模型时,它不起作用,但是当我使用像
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
Date startTime = cal.getTime();
cal.set(Calendar.HOUR, 23);
cal.set(Calendar.MINUTE, 59);
Date endTime = cal.getTime();
System.out.println(startTime);
System.out.println(endTime);
// The Calendar field seems to get ignored and overriden
// by the UI delegate based on what part of the field
// the cursor is current on (hour or minute)
SpinnerDateModel model = new SpinnerDateModel(startTime, null, endTime, Calendar.MINUTE);
JSpinner spinner = new JSpinner(model);
spinner.setEditor(new JSpinner.DateEditor(spinner, "HH:mm"));
spinner.setValue(startTime);
它很好用
此时我的“建议”不是使用自定义模型,而是通过所需的工厂方法手动构建模型
更新。。。
由于围绕JSpinner
和jforamtedtextfield
的复杂性,我放弃了让JSpinner
处理时间的尝试。相反,我通常会使用单独的字段来管理状态的复杂性
我从修改你的模型开始
public class SpinnerWindowModel extends SpinnerNumberModel {
private Calendar calendar;
private int calendarField;
public SpinnerWindowModel(int calendarField, Calendar calendar, int value, int min, int max, int step) {
super(value, min, max, step);
this.calendar = calendar;
}
@Override
public void setValue(Object value) {
super.setValue(value);
System.out.println(value);
}
public int getCalendarField() {
return calendarField;
}
@Override
public Object getPreviousValue() {
Object obj = super.getPreviousValue();
if (obj instanceof Integer) {
int fld = getCalendarField();
calendar.set(fld, (int)obj);
return obj;
}
return getValue();
}
@Override
public Object getNextValue() {
Object obj = super.getNextValue();
if (obj instanceof Integer) {
int fld = getCalendarField();
calendar.set(fld, (int)obj);
return obj;
}
return getValue();
}
}
然后将其应用到字段中
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
Date startTime = cal.getTime();
cal.set(Calendar.HOUR, 23);
cal.set(Calendar.MINUTE, 59);
Date endTime = cal.getTime();
System.out.println(startTime);
System.out.println(endTime);
SpinnerWindowModel hourModel = new SpinnerWindowModel(Calendar.HOUR, cal, 0, 0, 23, 1);
SpinnerWindowModel minuteModel = new SpinnerWindowModel(Calendar.HOUR, cal, 0, 0, 59, 15);
JSpinner hour = new JSpinner(hourModel);
JSpinner minute = new JSpinner(minuteModel);
add(hour);
add(new JLabel(":"));
add(minute);
现在,回到这一点,分钟字段不会滚动小时字段。我确实考虑过在分钟模型上使用一个更改侦听器,但问题是,您不知道字段是上升还是下降,因此没有简单的方法来确定您应该以哪种方式滚动小时
我将扩展这个概念,使用两个独立的JTextField
s(应用适当的DocumentFilter
s)和一个“滚动”控件。想法是,滚动控制(即上下按钮)会影响聚焦区域。然后,您可以在触发滚动控制时提供适当的状态信息,以允许字段确定它们应该做什么以及它们应该如何相互影响
这其中的许多内容可以汇总到一个模型中,该模型控制一个Calendar
(或者最好是LocalTime
)对象,该对象将更改基础日期值并通知需要更改的字段
我相信这种方法将为您提供所需的控制级别,为小时和分钟提供不同的步进速率,同时为用户交互提供灵活性(如果愿意,我可以手动或通过滚动控制输入数字)
更新。。。最后
因此,基于,基础的JFormattedTextField
无法验证该值,因为时间格式正在丢弃该值的“日期”部分,仅保留该时间,这会导致最小/最大值检查失败
相反,我们需要将最小/最大值的“日期”部分定义为我们可以控制的(并且更容易定义)。这也意味着任何输入都必须约束到这个特定的时间点
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(1970, Calendar.JANUARY, 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
Date startTime = cal.getTime();
cal.set(1970, Calendar.JANUARY, 23, 59, 0);
cal.set(Calendar.MILLISECOND, 0);
Date endTime = cal.getTime();
System.out.println(startTime);
System.out.println(endTime);
Calendar value = Calendar.getInstance();
value.set(1970, Calendar.JANUARY, 0, 0, 0);
value.set(Calendar.MILLISECOND, 0);
System.out.println(value.getTime());
// The Calendar field seems to get ignored and overriden
// by the UI delegate based on what part of the field
// the cursor is current on (hour or minute)
SpinnerDateModel model = new SpinnerDateModel(value.getTime(), startTime, endTime, Calendar.MINUTE);
JSpinner spinner = new JSpinner(model);
spinner.setEditor(new JSpinner.DateEditor(spinner, "HH:mm"));
spinner.setValue(value.getTime());
add(spinner);
这让我更新您的模型,以支持多步状态
public class SpinnerWindowModel extends SpinnerDateModel {
public SpinnerWindowModel() {
super();
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(1970, Calendar.JANUARY, 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
Date startTime = cal.getTime();
cal.set(1970, Calendar.JANUARY, 23, 59, 0);
cal.set(Calendar.MILLISECOND, 0);
Date endTime = cal.getTime();
System.out.println(startTime);
System.out.println(endTime);
Calendar value = Calendar.getInstance();
value.set(1970, Calendar.JANUARY, 0, 0, 0);
value.set(Calendar.MILLISECOND, 0);
setStart(startTime);
setEnd(endTime);
setValue(value.getTime());
setCalendarField(Calendar.MINUTE);
}
@Override
public Object getPreviousValue() {
int fld = getCalendarField();
Object value = super.getPreviousValue();
if (fld == Calendar.MINUTE) {
Calendar cal = Calendar.getInstance();
cal.setTime(getDate());
cal.add(Calendar.MINUTE, -15);
value = cal.getTime();
}
return value;
}
@Override
public Object getNextValue() {
int fld = getCalendarField();
Object value = super.getNextValue();
if (fld == Calendar.MINUTE) {
Calendar cal = Calendar.getInstance();
cal.setTime(getDate());
cal.add(Calendar.MINUTE, 15);
value = cal.getTime();
}
return value;
}
}
我将试验你的建议。我的问题是我只需要在15分钟的间隔内增加分钟。我将尝试另一个实例化器,看看是否能获得更好的结果。老实说,我很久以前就放弃了微调器(除了简单的数字功能),而是开发了-虽然这不完全是您想要的,但重点是,我不会试图将小时和分钟作为单个元素来处理,而是使用两个数字微调器,一个代表小时,一个代表分钟,这样你就可以在两个不同的模型中定义你的交互。自从我搞砸了这件事已经有一段时间了,但是由于记忆模糊,ui代理可以做出一系列你可能无法控制的选择(很容易),所以我可能无法确定编辑器试图增加哪个字段,这比我想象的更糟。你的成功是因为你没有设定开始时间。如果我不设置开始时间,我可以使我的模型看起来有效。真正的问题是,它不听取开始时间或停止时间,小时字段只是从0旋转到24。我确实需要找到另一种方法来做到这一点。我已经花了太多时间了。这只是一个原型。SpinnerDateModel的第一个参数是开始时间