【问题标题】:How to make JTextField or JFormattedTextField accept input only if it matches a REGEX pattern?如何使 JTextField 或 JFormattedTextField 仅在匹配 REGEX 模式时才接受输入?
【发布时间】:2012-11-28 16:54:32
【问题描述】:

我希望我的程序中的一些JTextField 仅在与特定的Pattern 匹配时才接受新输入。

我知道JFormattedTextField 的面具,这不是我想要的。

对于每个新的输入,文本应该只接受符合特定正则表达式模式流程的更改。

由于“需要正则表达式”的情况,这必须使用正则表达式来完成,例如输入是否应该接收自身的一部分。举个例子可以更好地理解这一点:

假设我的正则表达式是"(\\d{2})-bk\\d{3}\\.\\1"。 对于"123-bk001." 的输入,接下来输入的字符必须等于第一组,这意味着只有当它们分别等于123 时,才应接受3 个输入的字符。 “456-bk404”的输入。将要求下一个字符为 "456"

我该怎么做?


编辑:

这个例子只是为了说明没有正则表达式很难解决的一种情况,我的实际使用不限于此。因此,如果可能,答案应该具有更广泛的可用性(如问题的标题所示),而不是针对此示例。

但如果这不可能,或者比针对少数 (3-5) 种不同情况实施特定解决方案更难,请随时告知。

【问题讨论】:

  • 您可以检查 java Format 中的正则表达式,它可以与 JFormattedTextField 一起使用。你可以找到JFormattedTextFieldhere的示例
  • @Robin - 你能提供一个链接吗?我似乎在Format 的文档中找不到任何与正则表达式相关的内容。
  • 您可以编写自己的Format,在其中基于正则表达式进行验证。我不知道有任何开箱即用的 Format 提供此功能
  • @Robin - 在Format 的结构中将应用验证?我猜这是.format() 方法,但我不确定。 --- 之后如何将FormatTextComponent 集成,以便在发生无效输入时阻止它?
  • @Robin(我猜:-)可能意味着您必须实现一个自定义格式/ter,它使用正则表达式(核心不支持它,公平的)来解析和允许/拒绝输入。我首先看的是 DefaultFormatter:它安装了 Navigation- 和 DocumentFilters,您可能可以对其进行调整(但从未尝试过)

标签: java swing formatting block mask


【解决方案1】:

【讨论】:

  • 如示例所示,在这种情况下,不需要的字符的定义是动态的。相同的正则表达式应该接受111-bk001.111222-bk002.222。但如果最后 3 位数字与前 3 位不同(或正则表达式中指定的任何组),则不接受最后 3 位数字。
  • 对不起,要么我不明白如何应用这种方法,要么这不起作用。 --- 我可以为更简单的事情设置它,例如只允许正数,方法是覆盖 insertString()replace() 以将 replaceAll("\\D++") 应用于 stringtext 参数。 --- 但是当涉及到我的预期目的或任何组合模式时,使用Matcher 来匹配我想要的并排除其他所有内容都无法按预期工作。
  • 我有点理解DocumentFilter的用法,但是我不明白如何让它在模式完成之前接受正则表达式模式的匹配。 --- 例如,"123-"“匹配”模式的一部分,但不是全部。我需要做类似(currentText + newInput).matchesPatternPartially()==true 的检查,但我不知道如何从过滤器附加到的文档中获取currentText,也不知道如何制作matchesPatternPartially() 之类的函数。跨度>
【解决方案2】:

我的直觉方法是使用 DocumentFilter 并根据测试字符串的长度修改您正在测试的正则表达式。因此,如果您的测试字符串长度为 10 个字符,那么您用来测试它的正则表达式是 "(\\d{2})-bk\\d{3}\\.""\\d\\d\\d-bk\\d\\d\\d\\d\\."。这将通过"123-bk0001.",但失败"123-bk000a."

您要处理的每个正则表达式都需要进行一些自定义(例如,根据测试字符串的长度将括号放在正则表达式中的正确位置),但我认为没有办法制作基于长度的正则表达式动态(这是您所追求的)。

import javax.swing.*;
import javax.swing.text.*;

public class JTextFieldSuperVerified extends Box{

    public JTextFieldSuperVerified() {
        super(BoxLayout.Y_AXIS);

        final JTextField textBox = new JTextField(20);

        ((AbstractDocument)textBox.getDocument()).setDocumentFilter(new DocumentFilter(){

            public void insertString(DocumentFilter.FilterBypass fb,int offset,String string,AttributeSet attr) throws BadLocationException{
                StringBuilder newString = new StringBuilder(textBox.getText());
                //Recreate the insert for testing
                newString.insert(offset, string);
                if(verifyText(newString.toString())){
                    fb.insertString(offset, string, attr);
                }

            }

            public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException{
                StringBuilder newString = new StringBuilder(textBox.getText());
                //Recreate the delete for testing
                newString.delete(offset, offset + length);
                if(verifyText(newString.toString())){
                    fb.remove(offset, length);
                }
            }


            public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException{
                StringBuilder newString = new StringBuilder(textBox.getText());
                //Recreate the replace for testing
                newString.replace(offset, offset + length, text);
                if(verifyText(newString.toString())){
                    fb.replace(offset, length, text, attrs);
                }
            }

            //make sure the change is allowed
            public boolean verifyText(String s){
                boolean result = true;
                //Our basic regex to test
                StringBuilder regexPattern = new StringBuilder("\\d\\d\\d-bk\\d\\d\\d\\d\\.\\1");


                if(s.length() < 15){
                    //How we modify the regex based on how long the string we're testing is
                    if(s.length() < 4)
                        regexPattern.delete(s.length() * 2, regexPattern.length());
                    else if(s.length() < 7)
                        regexPattern.delete(s.length() + 3, regexPattern.length());
                    else if(s.length() < 12)
                        regexPattern.delete((s.length() - 3) * 2 + 3, regexPattern.length());
                    else if(s.length() < 15){
                        regexPattern.insert((s.length() - 11) * 2, ')');
                        regexPattern.insert(0, '(');
                    }
                    System.out.println(regexPattern.toString());
                    result = s.matches(regexPattern.toString());

                }else{
                    //Fail everything over 14 chars
                    result = false;
                }

                return result;
            }

        });

        add(textBox);

    }

    public static void main(String[] args){
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JTextFieldSuperVerified());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

【讨论】:

    猜你喜欢
    • 2020-02-09
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 2018-05-29
    相关资源
    最近更新 更多