2015-05-25 9 views
1

我试图实现自己JSpinner模型来接受enumeration(包括I18N),所以我不喜欢的是:定制JSpinner的模型不能正常工作

searchSpinner.setModel(new AbstractSpinnerModel() { 

    int index = 0; 
    int minIndex = 0; 
    int maxIndex = MY_ENUM.values().length - 1; 
    Object selected = MY_ENUM.values()[index]; 

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

    @Override 
    public void setValue(Object value) { 
     selected = value; 
     fireStateChanged(); 
    } 

    @Override 
    public Object getNextValue() { 
     if (index < maxIndex) { 
      index++; 
     } 
     fireStateChanged(); 
     return MY_ENUM.values()[index]; 
    } 

    @Override 
    public Object getPreviousValue() { 
     if (index > minIndex) { 
      index--; 
     } 
     fireStateChanged(); 
     return MY_ENUM.values()[index]; 
    } 

    @Override 
    public void addChangeListener(ChangeListener l) { 

    } 

    @Override 
    public void removeChangeListener(ChangeListener l) { 

    } 
}); 

的问题是,没有工作,甚至微调列表看起来像已禁用。我究竟做错了什么?

UPDATE:基于第一个答案

+0

'fireStateChanged'函数做了什么? – hrskrs

回答

1

您应该使用ChangeListener来通知模型更改的视图。

spinner = new JSpinner(new SpinnerModel() { 
    private ChangeListener l; 

    @Override 
    public void setValue(Object value) { 
     ... 

     if(l != null) { 
      l.stateChanged(new ChangeEvent(this)); 
     } 
    } 

    ... 

    @Override 
    public void addChangeListener(ChangeListener l) { 
     this.l = l; 
    } 

    @Override 
    public void removeChangeListener(ChangeListener l) { 
     if(this.l == l) { 
      this.l = null; 
     } 
    } 
}); 

编辑:您可以使用列表中登记的许多听众。

+0

Juste改变这个:if(this.l == l)with if (this.l!= l),你的答案正常工作 –

+0

这不是一个错误。要正确删除侦听器,必须提交相同的侦听器。在这种情况下,没有什么问题,但是如果指出删除的内容非常重要。 –

+0

此答案不正确,因为模型不应要求侦听器通知其自己的更改。正确的解决方案是启动通知方法。 –

3

您应该AbstractSpinnerModel扩展(注意新人们对他的问题 - 请注意,他的原来的问题已经实现给SpinnerModel接口的类后来他改变了他的代码。反映我的建议),并确保在适当时调用fireStateChanged()方法。你也没有考虑到边缘情况和超边缘情况。

例如,

import javax.swing.*; 
import javax.swing.JSpinner.DefaultEditor; 

public class MySpinnerPanel extends JPanel { 
    public static void main(String[] args) { 
     JSpinner spinner = new JSpinner(new MyEnumSpinnerModel()); 
     JSpinner.DefaultEditor editor = (DefaultEditor) spinner.getEditor(); 
     editor.getTextField().setColumns(5); 

     JPanel panel = new JPanel(); 
     panel.add(spinner); 
     JOptionPane.showMessageDialog(null, panel); 
    } 
} 

enum MyEnum { 
    FE, FI, FO, FUM, FOO, FUBAR, SPAM 
} 

class MyEnumSpinnerModel extends AbstractSpinnerModel { 
    private int index = 0; 

    @Override 
    public Object getValue() { 
     return MyEnum.values()[index]; 
    } 

    @Override 
    public void setValue(Object value) { 
     if (value instanceof MyEnum) { 
     index = ((MyEnum) value).ordinal(); 
     fireStateChanged(); 
     } else { 
     String text = value.toString() + " is not a valid enum item"; 
     throw new IllegalArgumentException(text); 
     } 
    } 

    @Override 
    public Object getNextValue() { 
     if (index >= MyEnum.values().length - 1) { 
     return null; 
     } else { 
     return MyEnum.values()[index + 1]; 
     } 
    } 

    @Override 
    public Object getPreviousValue() { 
     if (index <= 0) { 
     return null; 
     } else { 
     return MyEnum.values()[index - 1 ]; 
     } 
    } 
} 

编辑

注意,模型本身不应该要求一个监听器,通知视图(根据对方的回答这个问题),因为这是在AbstractSpinnerModel做什么内部。它是fireStateChange()方法是模型本身应该调用以触发此通知的方法,与Swing中大多数其他所有类似的模型结构(如您创建的从AbstractTableModel派生的任何TableModel对象)一样。有关详细信息,请参阅SpinnerListModel的源代码。你的代码应该模仿这个类。

+0

它没有工作:( –

+0

@HoussemBdr:请参阅编辑回答 –

+0

@houssem请注意,你接受的答案是kludge,并不正确 –