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

我正在调整这里的代码:

值更改侦听器到JTextField

编辑2

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

STRING:STRING:10 VALS:10 STRING:STRING:10 VALS:10 STRING: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 (stringValue100){ 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”中的exceptionjava.lang.NumberFormatException:对于输入字符串:“”at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)at java.lang.Integer.parseInt(Integer.java: 504)at com.NResearch.ValueAtRisk.Sigma $ 7.warn(Sigma.java:626)的java.lang.Integer.parseInt(Integer.java:527)at com.NResearch.ValueAtRisk.Sigma $ 7.removeUpdate(Sigma.java) :619)at javax.swing.text.AbstractDocument.fireRemoveUpdate(AbstractDocument.java:260)at javax.swing.text.AbstractDocument.handleRemove(AbstractDocument.java:623)at javax.swing.text.AbstractDocument.remove(AbstractDocument。 java:591)at javax.swing.text.AbstractDocument.replace(AbstractDocument.java:667)at javax.swing.text.JTextComponent.setText(JTextComponent.java:1718)at javax.swing.JFormattedTextField $ AbstractFormatter.install(JFormattedTextField) .java:949)javax.swing.text.DefaultFormatter.install(DefaultFormatter.java:124)at 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)在java.awt.Component.processEvent(Component.java:6261)的java.awt.Container.processEvent(Container.java:2229)中,java.awt.Component.dispatchEventImpl(Component.java:4861),位于java.awt。位于java.awt.DefaultKeyboardFocusManager.typeAheadAssertions的java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1895)上的java.awt.Component.dispatchEvent(Component.java:4687)上的Container.dispatchEventImpl(Container.java:2287)(DefaultKeyboardFocusManager) .java:938)java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:570)at java.awt.Component.dispatchEventImpl(Component.java:4731)at java.awt.Container.dispatchEventImpl(Container.java:2287)在java.awt.E的java.awt.Component.dispatchEvent(Component.java:4687) 在java.awt.EventQueue $ 3上的java.awt.EventQueue.access $ 200(EventQueue.java:103)上的ventQueue.dispatchEventImpl(EventQueue.java:735)java.awt.EventQueue $ 3.run(EventQueue.java:694) java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:76)java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:)的java.security.AccessController.doPrivileged(Native Method)中运行(EventQueue.java:692) 87)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 。保护域$ 1.doIntersectionPrivilege(ProtectionDomain.java:76)位于java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)的java.awt.EventQueread.pumpEventsForFilter的java.awt.EventQueue.dispatchEvent(EventQueue.java:705) (EventDispatchThread.java:161)位于j的java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150) 位于java.awt.EventDispatchThread.run的java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)中的ava.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)(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 (stringValue100){ JOptionPane.showMessageDialog(null, "Error: Please enter number bigger than 0", "Error Massage", JOptionPane.ERROR_MESSAGE); } } }); 

自定义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. 你可以捕获exception
  2. 你可以检查一个“空” String

就个人而言,我想两个都做……

 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(); } } } 

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

您可以查看validation输入 ,它将允许您在字段失去焦点时validation输入,这个人可能是更好的选择。

如果您不特别需要JSpinnerfunction(在序列中上下运行值),您可以查看使用DocumentFilter ( 例如 ),这将允许您控制进入该字段的内容。 您应该知道将DocumentFilter添加到JSpinner是不可能的(或者足够接近它):P

Exception表示传递给Integer.parseInt(..)的String是一个空字符串。 因此,请确保检查((JSpinner.DefaultEditor)spin2.getEditor()).getTextField().getText()为null并将其传递给Integer.parseInt(..)之前为空

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

这被certificate是后方巨大的痛苦。 我想立即为我的文本字段背景着色。 最后制作一个覆盖我想要使用的编辑器的编辑器,然后相应地将其设置为微调编辑器。 到目前为止似乎对我有用。

添加一个带有以下内容的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));