在 JTextField 中键入阿拉伯数字

发布于 2024-11-17 04:36:51 字数 970 浏览 5 评论 0原文

我试图在 JTextField 中输入阿拉伯数字,并使用 DocumentListener 如下:

txtName.getDocument().addDocumentListener(this);

...

public void insertUpdate(DocumentEvent e){setLabel();}
public void removeUpdate(DocumentEvent e){setLabel();}
public void changedUpdate(DocumentEvent e){}

public void setLabel()
{
    String s = txtName.getText();

    s = s.replace('0','\u0660');
    s = s.replace('1','\u0661');
    s = s.replace('2','\u0662');
    s = s.replace('3','\u0663');
    s = s.replace('4','\u0664');
    s = s.replace('5','\u0665');
    s = s.replace('6','\u0666');
    s = s.replace('7','\u0667');
    s = s.replace('8','\u0668');
    s = s.replace('9','\u0669');
    s = s.replace('.',',');

    txtName.setText(s);
}

但我在 txtName.setText(s); 处收到错误>

错误是:

Exception occurred during event dispatching:
java.lang.IllegalStateException: Attempt to mutate in notification

I am trying to type Arabic numbers in a JTextField and I used DocumentListener as follows:

txtName.getDocument().addDocumentListener(this);

...

public void insertUpdate(DocumentEvent e){setLabel();}
public void removeUpdate(DocumentEvent e){setLabel();}
public void changedUpdate(DocumentEvent e){}

public void setLabel()
{
    String s = txtName.getText();

    s = s.replace('0','\u0660');
    s = s.replace('1','\u0661');
    s = s.replace('2','\u0662');
    s = s.replace('3','\u0663');
    s = s.replace('4','\u0664');
    s = s.replace('5','\u0665');
    s = s.replace('6','\u0666');
    s = s.replace('7','\u0667');
    s = s.replace('8','\u0668');
    s = s.replace('9','\u0669');
    s = s.replace('.',',');

    txtName.setText(s);
}

but I got an error at txtName.setText(s);

and the error was:

Exception occurred during event dispatching:
java.lang.IllegalStateException: Attempt to mutate in notification

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

挽梦忆笙歌 2024-11-24 04:36:51

如果您阅读了 DocumentListener API,你会明白为什么会出现这个错误:

DocumentEvent 通知基于 JavaBeans 事件模型。无法保证传递给侦听器的顺序,并且在对文档进行进一步更改之前必须通知所有侦听器。这意味着 DocumentListener 的实现可能不会改变事件源(即关联的文档)。

考虑使用 DocumentFilter 代替。

例如,

import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.PlainDocument;

@SuppressWarnings("serial")
public class DocListenerProblem extends JPanel {
   private static final String REPLACE_CHARS = "0123456789.";
   private JTextField txtName = new JTextField(20);

   public DocListenerProblem() {
      add(txtName);
      PlainDocument doc = (PlainDocument) txtName.getDocument();
      doc.setDocumentFilter(new MyDocumentFilter());
   }

   private class MyDocumentFilter extends DocumentFilter {

      @Override
      public void insertString(FilterBypass fb, int offset, String text,
               AttributeSet attr) throws BadLocationException {
         if (REPLACE_CHARS.contains(text)) {
            text = doSwap(text);
         }
         super.insertString(fb, offset, text, attr);
      }

      @Override
      public void replace(FilterBypass fb, int offset, int length, String text,
               AttributeSet attrs) throws BadLocationException {
         if (REPLACE_CHARS.contains(text)) {
            text = doSwap(text);
         }
         super.replace(fb, offset, length, text, attrs);
      }

      @Override
      public void remove(FilterBypass fb, int offset, int length)
               throws BadLocationException {
         super.remove(fb, offset, length);
      }
   }

   public String doSwap(String text) {
      StringBuilder sb = new StringBuilder();
      for (char c : text.toCharArray()) {
         if (REPLACE_CHARS.contains(String.valueOf(c))) {
            if (c == '.') {
               c = ',';
            } else {
               c = (char) ('\u0660' - '0' + c);
            }
         }
         sb.append(c);
      }
      return sb.toString();
   }

   private static void createAndShowUI() {

      JFrame frame = new JFrame("DocListenerProblem");
      frame.getContentPane().add(new DocListenerProblem());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }

}

If you read the DocumentListener API, you'll see why this error occurred:

The DocumentEvent notification is based upon the JavaBeans event model. There is no guarantee about the order of delivery to listeners, and all listeners must be notified prior to making further mutations to the Document. This means implementations of the DocumentListener may not mutate the source of the event (i.e. the associated Document).

Consider using a DocumentFilter instead.

e.g.,

import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.PlainDocument;

@SuppressWarnings("serial")
public class DocListenerProblem extends JPanel {
   private static final String REPLACE_CHARS = "0123456789.";
   private JTextField txtName = new JTextField(20);

   public DocListenerProblem() {
      add(txtName);
      PlainDocument doc = (PlainDocument) txtName.getDocument();
      doc.setDocumentFilter(new MyDocumentFilter());
   }

   private class MyDocumentFilter extends DocumentFilter {

      @Override
      public void insertString(FilterBypass fb, int offset, String text,
               AttributeSet attr) throws BadLocationException {
         if (REPLACE_CHARS.contains(text)) {
            text = doSwap(text);
         }
         super.insertString(fb, offset, text, attr);
      }

      @Override
      public void replace(FilterBypass fb, int offset, int length, String text,
               AttributeSet attrs) throws BadLocationException {
         if (REPLACE_CHARS.contains(text)) {
            text = doSwap(text);
         }
         super.replace(fb, offset, length, text, attrs);
      }

      @Override
      public void remove(FilterBypass fb, int offset, int length)
               throws BadLocationException {
         super.remove(fb, offset, length);
      }
   }

   public String doSwap(String text) {
      StringBuilder sb = new StringBuilder();
      for (char c : text.toCharArray()) {
         if (REPLACE_CHARS.contains(String.valueOf(c))) {
            if (c == '.') {
               c = ',';
            } else {
               c = (char) ('\u0660' - '0' + c);
            }
         }
         sb.append(c);
      }
      return sb.toString();
   }

   private static void createAndShowUI() {

      JFrame frame = new JFrame("DocListenerProblem");
      frame.getContentPane().add(new DocListenerProblem());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文