Ввод арабских чисел в JTextField - PullRequest
1 голос
/ 24 июня 2011

Я пытаюсь набрать арабские цифры в 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

1 Ответ

4 голосов
/ 24 июня 2011

Если вы прочитаете 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();
         }
      });
   }

}
...