Java « запретить ввод символов в jtextfield

Есть определенный набор символов которые можно вводить. Например маска телефона, или IP адрес.
Есть ли стандартный способ настроить jtextfield на ввод по маске/шаблону?

1 ответов


Специального механизма, именно у JTextField нет, но решение есть.

javax.swing.JTextField наследует от javax.swing.text.JTextComponent механизм CaretListener:

Каждое изменение позиции знака вставки генерирует событие CaretEvent. Эти события можно прослушивать реализовав интерфейс CaretListener.

CaretListener определяет только один метод:


void caretUpdate(CaretEvent ce)
 

Соответственно, любую поверку можно организовать через этот метод. Остается только дописать буфферизацию строки, а доступ к полю у нас есть через set/getText.

Так что это делается вручную:

...
JTextField textField;
...
textField = new JTextField(255);
...
textField.addCaretListener( new CaretListener() {
   public void caretUpdate (CaretEvent ce) {
       ...
       String value = textFiled.getText;
       <обработка>
       textField.setText(<либо строка из буфера, либо та, которая есть>);
       ...
   }
});
 

А если често, то нужно использовать JFormattedTextField)

Если же Вы все таки решитесь обратиться к JFormattedTextField, то можно использовать MaskFormatter:


   ...
   MaskFormatter formatter = new MaskFormatter("###-####");
   formatter.setPlaceholderCharacter('_');
   ...
   JFormattedTextField textField = new JFormattedTextField(formatter);
   ...
 

Аргументом в конструкторе является маска. Вот параметры, которые могут быть определены в маске и что они означают:
# - любое правильное (разрешенное) число;
' - удаление символа;
? - любая буква;
A - любая буква или число ;
* - что-нибудь;
U - любая буква, но все строчные станут заглавными;
L - заглавные буквы делает строчными;
H - определяет шестнадцатиричные символы.


Пробовал сделать так, как описано в первом ответе. При этом возникла проблема. Если в реализации caretUpdate использовать textField.setText(), то возникает бесконечный цикл - метод .setText() вызывает событие caretUpdate же.
Мой вариант фильтрации вводимых символов:


    public static String digitsOnlyFilter (String value) {
       int len = value.length();
       String result = "";
       boolean oneget = false;

        for(int i = 0; i < len; i++) {
            char ch = value.charAt(i);

            if(Character.isDigit(ch)) {
                result += value.substring(i, i+1);
            } else if ((ch == '.') && !oneget) {
                oneget = true;
                result += value.substring(i, i+1);
            }
        }
       return result;
    }

    public static void addKeyFilter(final JTextField field) {
        field.addKeyListener(new KeyListener() {
            public void keyTyped(KeyEvent e) {}
            public void keyPressed(KeyEvent e) {}
            public void keyReleased(KeyEvent e) {
                field.setText(digitsOnlyFilter(field.getText()));
            }
        });
    }
 
Этот метод не дает вводить в поле ничего, кроме цифр и точки.

Пример использования:

...
JTextField tfSquare = new JTextField();
addKeyFilter(tfSquare);
...
 

Запретить ввод символов можно и проще:


jTextField.addKeyListener(new java.awt.event.KeyAdapter() {
        public void keyTyped(java.awt.event.KeyEvent e) {
          char a = e.getKeyChar();
          if (!Character.isDigit(a)
              && (a != '.')
              && (a != '\b')) {
            e.consume();
          }
        }
      });
 
Если по какой то причине Вас не устроил метод предложенный в первом ответе, можно самостоятельно реализовать логику маски. На пример, для реализации поля ввода ip адреса можно реализовать метод:

private boolean isCorrectKey(char key, int position) {
    /* Если нажата кнопка backspace */
    if (key == '\b') {
      return true;
    }
    /* Если вводится цифра */
    if (Character.isDigit(key)) {
      return
        (position >= 0 && position < 3)
        || (position >= 4 && position < 7)
        || (position >= 8 && position < 11)
        || (position >= 12 && position < 15);
    }
    /* Если вводится точка */
    if (key == '.') {
      return
        (position == 3)
        || (position == 7)
        || (position == 11);
    }
    /* Все остальные случаи */
    return false;
  }
 
*Данный метод не предусматривает проверки на диапазон IP адреса тк приводится для наглядности.


jTextField.addKeyListener(new java.awt.event.KeyAdapter() {
        public void keyTyped(java.awt.event.KeyEvent e) {
          char key = e.getKeyChar();
          int position = jTextField.getText().length();
          if (!isCorrectKey(key, position)) {
            e.consume();
          }
        }
      });
 

Надо заметить, что от вставки неверного текста это не спасет. На мой взгляд, в любом случае, после потери фокуса полем ввода надо проверять его текст по маске.