在JTextField中键入阿拉伯数字

在JTextField中键入阿拉伯数字

我试图在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

最佳答案

如果您阅读DocumentListener API,将会看到发生此错误的原因:


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


考虑改用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();
         }
      });
   }

}

关于java - 在JTextField中键入阿拉伯数字,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6470260/

10-09 18:29