java - 如何从另一个 JtextField 更新 JTextField

标签 java swing jtextfield documentlistener documentfilter

我正在制作一个用户界面,其中有两个 jtextfields。我想要的是当用户输入第一个 jtextfield 它应该以 1 的增量镜像在第二个 jtextfield 中,并且如果用户 在第二个 JtextField 中输入,它应该镜像到第一个 jtextfield 并减少 1.但是我收到类似 IllegalStateException:Attempt to mutate in notification. 的错误。

示例代码:

public class Sh extends JFrame 
{
 public Sh() 
{
super("SH");
JPanel panel = new JPanel();
getContentPane().add(panel, BorderLayout.NORTH);

final JTextField field = new JTextField(10);
panel.add(field); 

final JTextField field1 = new JTextField(10);
panel.add(field1);

  DocumentListener docListener = new DocumentListener(){

        @Override
        public void changedUpdate(DocumentEvent e) {
            updateLabel(e);
        }

        @Override
        public void insertUpdate(DocumentEvent e) {
            updateLabel(e);
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            updateLabel(e);
        }

        private void updateLabel(DocumentEvent e) {
     String text = field.getText();
                    String text1 = field1.getText();

                    if (!text.isEmpty()) {
                        int p = Integer.parseInt(text);
                        int i = (p + 1);
                        String s = String.valueOf(i);
                        field1.setText(s);
                    } else if (!text1.isEmpty()) {
                        int p = Integer.parseInt(text1);
                        int i = (p - 1);
                        String s = String.valueOf(i);
                        field.setText(s);
                    }

                }
    };
  field.getDocument().addDocumentListener(docListener);
  field1.getDocument().addDocumentListener(docListener); 

       DocumentFilter docFilter = new DocumentFilter(){
        @Override
        public void insertString(FilterBypass fb, int off, String str, AttributeSet attr)
                throws BadLocationException {
            fb.insertString(off, str.replaceAll("\\D++", ""), attr);  // remove non-digits
        }

        @Override
        public void replace(FilterBypass fb, int off, int len, String str, AttributeSet attr)
                throws BadLocationException {
            fb.replace(off, len, str.replaceAll("\\D++", ""), attr);  // remove non-digits
        }
    };   
 ((AbstractDocument) field.getDocument()).setDocumentFilter(docFilter); 
 ((AbstractDocument) field1.getDocument()).setDocumentFilter(docFilter); 

  }
   public static void main(String[] args)
   {
  Sh s = new Sh();
  s.setDefaultCloseOperation(EXIT_ON_CLOSE);
  s.pack();
  s.setVisible(true);
   }
 }

最佳答案

根据 MadProgrammer 的提议这是解决方案:

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;

/**
 * <code>Sh</code>.
 *
 * @author SMedvynskyy
 */
public class Sh extends JFrame
{
    public Sh()
    {
        super("SH");
        final JPanel panel = new JPanel();
        getContentPane().add(panel, BorderLayout.NORTH);

        final JTextField field = new JTextField(10);
        panel.add(field);

        final JTextField field1 = new JTextField(10);
        panel.add(field1);

        final DocumentListener docListener = new DocumentListener(){

            private Document originator;

            @Override
            public void changedUpdate(DocumentEvent e) {
                updateLabel(e);
            }

            @Override
            public void insertUpdate(DocumentEvent e) {
                updateLabel(e);
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                updateLabel(e);
            }

            private void updateLabel(DocumentEvent e) {
                if (null == originator) {
                    originator = e.getDocument();
                    String text = "";
                    try {
                        text = originator.getText(0, originator.getLength());
                    } catch (final Exception ex) {
                        ex.printStackTrace();
                    }

                    if (!text.isEmpty()) {
                        final int p = Integer.parseInt(text);
                        if (originator.equals(field.getDocument())) {
                            final int i = (p + 1);
                            final String s = String.valueOf(i);
                            field1.setText(s);
                        } else {
                            final int i = (p - 1);
                            final String s = String.valueOf(i);
                            field.setText(s);
                        }
                    } else {
                      field.setText(text);
                      field1.setText(text);
                    }

                    originator = null;
                }

            }
        };
        field.getDocument().addDocumentListener(docListener);
        field1.getDocument().addDocumentListener(docListener);

        final DocumentFilter docFilter = new DocumentFilter(){
            @Override
            public void insertString(FilterBypass fb, int off, String str, AttributeSet attr)
                    throws BadLocationException {
                fb.insertString(off, str.replaceAll("\\D++", ""), attr);  // remove non-digits
            }

            @Override
            public void replace(FilterBypass fb, int off, int len, String str, AttributeSet attr)
                    throws BadLocationException {
                fb.replace(off, len, str.replaceAll("\\D++", ""), attr);  // remove non-digits
            }
        };
        ((AbstractDocument) field.getDocument()).setDocumentFilter(docFilter);
        ((AbstractDocument) field1.getDocument()).setDocumentFilter(docFilter);

    }
    public static void main(String[] args)
    {
        final Sh s = new Sh();
        s.setDefaultCloseOperation(EXIT_ON_CLOSE);
        s.pack();
        s.setVisible(true);
    }
}

方法 JTextField.setText 会引发 DocumentEvent,因此如果您不特别避免它 - 您将遇到此问题(或无限递归)。

关于java - 如何从另一个 JtextField 更新 JTextField,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26274827/

相关文章:

java - 制作一个倒计时器

java - 在开关盒中使用 double 可能会失去精度

java - JTextFields 只接受数字的常用方法

java - 输入按钮抛出空指针异常

java - 只允许在 JTextField 中输入数字和符号 (-)

java - Windows 8.1 上的 Apache Maven 3.5.3 安装问题

java - 字符串空值检查

java - DefaultTableModel 不返回 dataVector 中的值

java - 按下按钮时 JTextField 自动更改值

java - 带有组合框和文本字段的简单 Jframe 以及标签中的结果