1

我希望JTextField我的程序中的一些只接受新输入,如果它匹配特定的Pattern.

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

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

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

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

我该怎么做?


编辑:

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

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

4

2 回答 2

2
于 2012-11-28T17:16:28.860 回答
0

我的直觉方法是使用 DocumentFilter 并根据测试字符串的长度修改您正在测试的正则表达式。因此,如果您的测试字符串长度为 10 个字符,那么您用来测试它的正则表达式是"(\\d{2})-bk\\d{3}\\."or "\\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);
    }
}
于 2012-12-04T18:02:25.820 回答