使用Subclassed SpinnerListModel将数字键入JSpinner

时间:2013-03-13 04:37:04

标签: java swing jspinner

我希望有一个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将所有内容保存为整数并且也可以。所以我不确定为什么我的整数不起作用,但SpinnerNumberModel会这样做。

2 个答案:

答案 0 :(得分:2)

我认为以下解决方案优于实现Formatter的建议,因为它不是格式化问题,而是限制可能值的问题,这应该是模型的责任。我有一个类似的问题,并绊倒这个线程解决方案,导致一个非常丑陋的实现。所以我希望我能想到的就是让你摆脱困境。

  

这会很好地生成模型,我可以使用JSpinner上的按钮移动值。但是,键入值不起作用。例如,如果微调器设置为3而我输入7,则它保持为3(可能是因为它不认为7是有效值)。这适用于SpinnerNumberModel,所以我不确定发生了什么。

这里的问题是使用setModel设置新模型具有根据模型类型更改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());
        }
    }
}

答案 1 :(得分:-1)

我认为你可以用字符串做,然后使用方法来获取数字。 像这样:

Spinner1(){
          String[] values={"1","3","5","7"};
          SpinnerModel model=new SpinnerListModel(values);
          JSpinner spinner=new JSpinner(model);
}
int getValue(Object obj){
    int out=0;
    return out=Integer.parseInt((String)obj);
}