我想要一个JSpinner来显示数字的非模式序列(例如,质数序列)。对于SpinnerNumberModel来说,这种模式太复杂了,因此我决定将SpinnerListModel子类化。构造函数如下所示:
public CustomSpinnerListModel() {
Vector<Integer> values = new Vector<Integer>();
values.add(1);
values.add(3);
values.add(5);
values.add(7);
this.setList(values);
}
这样就可以很好地生成模型,我可以使用JSpinner上的按钮浏览各个值。但是,输入值无效。例如,如果微调器设置为3,而我键入7,则它将保持为3(大概是因为它认为7不是有效值)。这适用于SpinnerNumberModel,所以我不确定发生了什么。
编辑:我发现,如果我将数字另存为字符串值,则输入有效。但是,SpinnerNumberModel将所有内容保存为Integers,并且也可以使用。所以我不确定为什么我的整数不起作用,但是SpinnerNumberModel起作用。
最佳答案
我认为以下解决方案比实现Formatter的建议更好,因为这不是格式化问题,而是限制可能值的问题,这应该由模型负责。我有一个类似的问题,并且绊脚石这个线程解决方案,导致实现非常丑陋。因此,希望我提出的建议能使您摆脱麻烦。
这样就可以很好地生成模型,我可以使用JSpinner上的按钮浏览各个值。但是,输入值无效。例如,如果微调器设置为3,而我键入7,则它将保持为3(大概是因为它认为7不是有效值)。这适用于SpinnerNumberModel,所以我不确定发生了什么。
这里的问题是,使用setModel设置新模型具有未记录的副作用,该副作用取决于Model的类型来更改JTextFieldEditor属性:
http://fuseyism.com/classpath/doc/javax/swing/JSpinner-source.html
默认情况下,JSpinner使用SpinnerNumberModel类的模型以及DefaultNumberEditor类的编辑器。将模型设置为SpinnerListModel时,它将改为使用ListEditor。在您的情况下,这是一个糟糕的选择,因为它要求您将每个素数输入到列表中,然后将其提供给SpinnerListModel进行输入验证。否则,正如您所指出的,您的输入将被忽略。
因此,这里的简单解决方案是将SpinnerNumberModel子类化,该子类允许任何数字,而不是特定的值列表:
class PrimeNumberModel extends SpinnerNumberModel {
Object currentValue;
@Override
public Object getNextValue() {
return findNextPrimeFrom(currentValue);
}
@Override
public Object getPreviousValue() {
return findPreviousPrimeFrom(currentValue);
}
@Override
public void setValue(Object o) {
throwOnNonePrime(o); //Verify Input
super.setValue(o);
}
private void throwOnNonePrime(Object o) {
try {
int num = Integer.valueOf(o.toString());
if(!isPrime(num))
throw new IllegalArgumentException(o.toString());
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException(o.toString());
}
}
}