如何使用DefaultEditor方法检查JSpinner字段上的手动编辑

时间:2014-01-03 11:46:40

标签: java swing jspinner

我正在调整此处的代码:

Value Change Listener to JTextField

编辑2

当我按向上微调箭头时,以下代码给出了无限循环的对话框:

STRING: STRING:10 VALS:10 串: STRING:10 VALS:10 串: STRING:10 VALS:10 .....

警告您需要使用taskmanager来杀死它。

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    JFrame F = new JFrame();
    F.setVisible(true);
    JPanel p = new JPanel();


    final JSpinner spin2 = new JSpinner();
    spin2.setModel(new SpinnerNumberModel(10, 10, 100, 1));

    JComponent comp = spin2.getEditor();
    JFormattedTextField field = (JFormattedTextField) comp.getComponent(0);
    DefaultFormatter formatter = (DefaultFormatter) field.getFormatter();
    formatter.setCommitsOnValidEdit(true);


    ((JSpinner.DefaultEditor)spin2.getEditor()).getTextField().getDocument().addDocumentListener(new DocumentListener() {
          public void changedUpdate(DocumentEvent e) {
                warn();
              }
              public void removeUpdate(DocumentEvent e) {
                warn();
              }
              public void insertUpdate(DocumentEvent e) {
                warn();
              }

              public void warn() {
                  String text = ((JSpinner.DefaultEditor)spin2.getEditor()).getTextField().getText();
                  JOptionPane.showMessageDialog(null,   "STRING: "+text, "Error Massage",     JOptionPane.ERROR_MESSAGE);
                  if (text != null && !text.trim().isEmpty()) {
                      int stringValue = Integer.parseInt(((JSpinner.DefaultEditor)spin2.getEditor()).getTextField().getText());
                      JOptionPane.showMessageDialog(null,
                              "VALS: "+spin2.getValue(), "Error Massage",
                              JOptionPane.ERROR_MESSAGE);
                     if (stringValue<10 || stringValue >100){
                       JOptionPane.showMessageDialog(null,
                          "Error: Number outside bounds", "Error Massage",
                          JOptionPane.ERROR_MESSAGE);
                     }

                  }
              }
            });


    p.add(spin2);   


    F.add(p);
    F.pack();
    F.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


}

编辑3

当无效时,背景变为红色,当字段失去焦点时,BUT值将恢复为之前(如果无效)。我希望能够在这一点上建立一个JOptionPane,表示值仍然无效,而不是恢复到之前:

        ((JSpinner.DefaultEditor)Position.getEditor()).getTextField().addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                //LOG.info("" + evt);
                if ("editValid".equals(evt.getPropertyName())) {
                    if (Boolean.FALSE.equals(evt.getNewValue())) {
                        SpinnerNumberModel model = (SpinnerNumberModel) Position.getModel();  

                        ((JSpinner.DefaultEditor)Position.getEditor()).getTextField().setBackground(Color.RED);
                        ((JSpinner.DefaultEditor)Position.getEditor()).getTextField().setToolTipText("Amount must be in range [ " + model.getMinimum() + " ... " + model.getMaximum() + " ] for this symbol");

                    }
                    else{
                        ((JSpinner.DefaultEditor)Position.getEditor()).getTextField().setBackground(Color.WHITE);
                    }
                }

            }
        });

/////////////////////////////////////////////// ////////////////////////////////////////////////// /

原始问题

但是如果我使用微调器放入低于下限的值。我在文本字段中得到一个“(”,这个错误:

线程中的异常“AWT-EventQueue-0”java.lang.NumberFormatException:对于输入字符串:“”     at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)     在java.lang.Integer.parseInt(Integer.java:504)     在java.lang.Integer.parseInt(Integer.java:527)     在com.NResearch.ValueAtRisk.Sigma $ 7.warn(Sigma.java:626)     在com.NResearch.ValueAtRisk.Sigma $ 7.removeUpdate(Sigma.java:619)     在javax.swing.text.AbstractDocument.fireRemoveUpdate(AbstractDocument.java:260)     在javax.swing.text.AbstractDocument.handleRemove(AbstractDocument.java:623)     在javax.swing.text.AbstractDocument.remove(AbstractDocument.java:591)     在javax.swing.text.AbstractDocument.replace(AbstractDocument.java:667)     at javax.swing.text.JTextComponent.setText(JTextComponent.java:1718)     在javax.swing.JFormattedTextField $ AbstractFormatter.install(JFormattedTextField.java:949)     在javax.swing.text.DefaultFormatter.install(DefaultFormatter.java:124)     在javax.swing.text.InternationalFormatter.install(InternationalFormatter.java:285)     在javax.swing.JFormattedTextField.setFormatter(JFormattedTextField.java:465)     在javax.swing.JFormattedTextField.setValue(JFormattedTextField.java:789)     在javax.swing.JFormattedTextField.processFocusEvent(JFormattedTextField.java:636)     at java.awt.Component.processEvent(Component.java:6261)     at java.awt.Container.processEvent(Container.java:2229)     at java.awt.Component.dispatchEventImpl(Component.java:4861)     at java.awt.Container.dispatchEventImpl(Container.java:2287)     at java.awt.Component.dispatchEvent(Component.java:4687)     at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1895)     at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:938)     at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:570)     at java.awt.Component.dispatchEventImpl(Component.java:4731)     at java.awt.Container.dispatchEventImpl(Container.java:2287)     at java.awt.Component.dispatchEvent(Component.java:4687)     at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)     at java.awt.EventQueue.access $ 200(EventQueue.java:103)     at java.awt.EventQueue $ 3.run(EventQueue.java:694)     at java.awt.EventQueue $ 3.run(EventQueue.java:692)     at java.security.AccessController.doPrivileged(Native Method)     at java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:76)     at java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:87)     at java.awt.EventQueue $ 4.run(EventQueue.java:708)     at java.awt.EventQueue $ 4.run(EventQueue.java:706)     at java.security.AccessController.doPrivileged(Native Method)     at java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:76)     at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)     at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)     at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)     at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)     at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)     at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)     at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

final JSpinner spin2 = new JSpinner();
spin2.setModel(new SpinnerNumberModel(10, 10, 100, 1));

JComponent comp = spin2.getEditor();
JFormattedTextField field = (JFormattedTextField) comp.getComponent(0);
DefaultFormatter formatter = (DefaultFormatter) field.getFormatter();
formatter.setCommitsOnValidEdit(true);


((JSpinner.DefaultEditor)spin2.getEditor()).getTextField().getDocument().addDocumentListener(new DocumentListener() {
          public void changedUpdate(DocumentEvent e) {
                warn();
              }
              public void removeUpdate(DocumentEvent e) {
                warn();
              }
              public void insertUpdate(DocumentEvent e) {
                warn();
              }

              public void warn() {
                  int stringValue = Integer.parseInt(((JSpinner.DefaultEditor)spin2.getEditor()).getTextField().getText());
                  JOptionPane.showMessageDialog(null,
                          "VALS: "+spin2.getValue(), "Error Massage",
                          JOptionPane.ERROR_MESSAGE);
                 if (stringValue<10 || stringValue >100){
                   JOptionPane.showMessageDialog(null,
                      "Error: Please enter number bigger than 0", "Error Massage",
                      JOptionPane.ERROR_MESSAGE);
                 }

              }
            });

4 个答案:

答案 0 :(得分:3)

自定义DocumentListeners和formattedTextField不能很好地相互配合,最好不要混合。相反,在文本字段上使用PropertyChangeListener来侦听其editValid属性的更改:每当更改为false时,您都可以通知用户

field.addPropertyChangeListener(new PropertyChangeListener() {

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        LOG.info("" + evt);
        if ("editValid".equals(evt.getPropertyName()) 
            &&  Boolean.FALSE.equals(evt.getNewValue())) {
          SpinnerNumberModel model = (SpinnerNumberModel) spin2.getModel();  
          JOptionPane.showMessageDialog(null,
          "Error: Number must be in range [" + model.getMinimum() + " ..." + model.getMaximum() + "]",
           "Error Massage",
          JOptionPane.ERROR_MESSAGE);

        }

    }
});
顺便说一下,个人而言,我同意Mad的观点 - 这种侵扰性通知往往会让我烦恼,也许也会影响你的用户..

答案 1 :(得分:2)

您有几个基本选择。

  1. 您可以捕获异常
  2. 您可以检查&#34;空&#34; String
  3. 就个人而言,我想同时做两件事......

    public void warn() {
        String text = ((JSpinner.DefaultEditor)spin2.getEditor()).getTextField().getText();
        if (text != null && !text.trim().isEmpty()) {
            try {
                int stringValue = Integer.parseInt(text);
                JOptionPane.showMessageDialog(null,
                      "VALS: "+spin2.getValue(), "Error Massage",
                      JOptionPane.ERROR_MESSAGE);
                if (stringValue<10 || stringValue >100){
                JOptionPane.showMessageDialog(null,
                  "Error: Please enter number bigger than 0", "Error Massage",
                  JOptionPane.ERROR_MESSAGE);
                }
            } catch (NumberFormatException exp) {
                exp.printStackTrace();
            }
        }
    }
    

    现在,作为用户,这可能只会让我烦恼。突出显示字段,发出哔哔声,更改工具提示,当然,在我脸上抛出一个对话框......嗯......

    您可以查看Validating Input,这样您就可以在字段失去焦点时验证输入,这个人可能是更好的选择。

    如果您不特别需要JSpinner的功能(在序列中上下运行值),您可以查看使用DocumentFilter({{3} }}),它将允许您控制进入该字段的内容。您应该知道将DocumentFilter添加到JSpinner ...:P

    是不可能的(或者足够接近它)

答案 2 :(得分:0)

Exception表示传递给Integer.parseInt(..)的String是一个空字符串。因此,在将((JSpinner.DefaultEditor)spin2.getEditor()).getTextField().getText()传递给Integer.parseInt(..)

之前,请务必检查{{1}}是否为null

你可以看看apache commons-io和StringUtils类,它们有很多好方法可以减轻检查空/空字符串的痛苦

答案 3 :(得分:0)

这被证明是后方的巨大痛苦。我想立即为文本字段背景上色。最终制作了一个可以覆盖我要使用的编辑器的编辑器,然后将其相应地设置为Spinners编辑器。到目前为止似乎为我工作。

添加一个带有以下内容的Java类(删除代码块周围的引号,我在使用堆栈溢出的编辑器时遇到了麻烦):

`public class CustomNumberEditor extends JSpinner.NumberEditor {
    public CustomNumberEditor( JSpinner spinner ) {
        super( spinner );
        ((DefaultFormatter ) ((JFormattedTextField) getComponent( 0 )).getFormatter()).setCommitsOnValidEdit( true );
    }
    @Override public void propertyChange(PropertyChangeEvent e) {
        super.propertyChange( e );
        if( e.getPropertyName().equals( "value" ) )
            doStuff( (int) e.getNewValue() );
    }
    private void doStuff( int value )
    {
        //do stuff
    }
}`

然后在添加微调器时,执行以下操作:

_quantitySpinner.setEditor(new CustomNumberEditor(_quantitySpinner));