我试图通过正则表达式避免在JTextField中输入无效的数字,但是当我输入有效的数字时,它也会去消耗方法来消耗。请指导我。

  private void txtphoneKeyTyped(java.awt.event.KeyEvent evt) {
   char c = evt.getKeyChar();
   String regex = "^(\\+93|0)?[7][0-9]{8}$";
   Pattern pattern = Pattern.compile(regex);
   Matcher matcher = pattern.matcher(String.valueOf(c));
   if(matcher.matches() == false){
      evt.consume();
   }
}

最佳答案

您不应该为此使用KeyListener。

一方面,您试图将单个键入的字符与整个电话号码模式进行匹配。 evt.getKeyChar()返回单个字符的事实应告诉您,它不可能与整个电话号码匹配。

正确的方法是使用JTextField的子类JFormattedTextField,而不是普通的JTextField。

String regex = "^(\\+93|0)?7[0-9]{8}$";
Pattern pattern = Pattern.compile(regex);

JFormattedTextField.AbstractFormatter formatter =
    new JFormattedTextField.AbstractFormatter() {
        private static final long serialVersionUID = 1;

        @Override
        public Object stringToValue(String text)
        throws ParseException {
            if (text != null && !pattern.matcher(text).matches()) {
                throw new ParseException(text, 0);
            }
            return text;
        }

        @Override
        public String valueToString(Object value) {
            return Objects.toString(value, null);
        }
    };

JTextField txtphone = new JFormattedTextField(formatter);


您实际上并不需要限制键入的键;如果用户键入无效字符,则该值将被拒绝,并且该字段将恢复为最后输入的正确值。但是,如果您坚持限制每个键入的字符,则可以使用DocumentFilter

Pattern allowedCharactersPattern = Pattern.compile("[0-9+]*");

DocumentFilter filter = new DocumentFilter() {
    @Override
    public void insertString(FilterBypass bypass,
                             int position,
                             String newText,
                             AttributeSet attr)
    throws BadLocationException {
        if (allowedCharactersPattern.matcher(newText).matches()) {
            super.insertString(bypass, position, newText, attr);
        }
    }

    @Override
    public void replace(FilterBypass bypass,
                        int position,
                        int length,
                        String newText,
                        AttributeSet attr)
    throws BadLocationException {
        if (allowedCharactersPattern.matcher(newText).matches()) {
            super.replace(bypass, position, length, newText, attr);
        }
    }
};

String regex = "^(\\+93|0)?7[0-9]{8}$";
Pattern pattern = Pattern.compile(regex);

JFormattedTextField.AbstractFormatter formatter =
    new JFormattedTextField.AbstractFormatter() {
        private static final long serialVersionUID = 1;

        @Override
        protected DocumentFilter getDocumentFilter() {
            return filter;
        }

        @Override
        public Object stringToValue(String text)
        throws ParseException {
            if (text != null && !pattern.matcher(text).matches()) {
                throw new ParseException(text, 0);
            }
            return text;
        }

        @Override
        public String valueToString(Object value) {
            return Objects.toString(value, null);
        }
    };

JTextField txtphone = new JFormattedTextField(formatter);


您可能想知道为什么allowedCharactersPattern是"[0-9+]*",而不是完整的电话号码模式。这是因为具有带有可移动光标的文本字段的原因之一是,用户一次只能输入一点信息,可能会乱序输入。例如,用户可以键入一些数字,然后使用箭头键将光标移到开头并键入“ +937”。最好在用户完成编辑后才实施模式。 stringToValue方法仍然强制执行整体模式。

关于java - 带JTextField事件的正则表达式不起作用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55672184/

10-12 05:52