java - 应用正则表达式的 JTextField 在应用文档之前不会接受值

标签 java regex swing numbers jtextfield

我有一个 JTextField,我已经覆盖了它的文档,这样我就可以阻止用户输入一些字符。其工作方式是我的 Document 扩展在其构造函数中接收正则表达式,然后根据正则表达式检查用户键入的任何内容:

public class ValidDocument extends PlainDocument
{
    private String regex;

    public ValidDocument(String regex)
    {
        this.regex = regex;
    }

    @Override
    public void insertString(int offs, String str, AttributeSet a)
    {
        if(str == null) return;

        try
        {
            if((this.getText(0, getLength()) + str).matches(regex))
                super.insertString(offs, str, a);
        }
        catch(BadLocationException ble)
        {
            System.out.println("Came across a BadLocationException");
        }
    }
}

但是,我遇到了一个问题,我只想显示有效浮点/ double 字的 JTextField 没有显示其初始值。我使用的代码如下:

float value = 25.0f;
JTextField textField = new JTextField("" + value);
textField.setDocument(new ValidDocument("^(\\-)?\\d*(\\.)?\\d*$"));

因此 JTextField 显示出来,但没有初始值。我尝试在该字段中输入 25.0,它接受了我最初预期的值。经过一番填充后,我尝试添加:

textField.setText("" + value);

它显示了值。我想到它可能接受我尝试放入 setText() 中的任何内容,因此我向其中添加了字母字符:

textField.setText("as" + value);

正如我所怀疑的,它包含字母字符,尽管正则表达式应该阻止这种情况。所以我的想法是,使用这个函数时,文档被绕过了。

任何人都可以解释为什么将 ValidDocument 应用于我的 JTextField 会删除我放置在文本字段构造函数中的文本吗?我还有其他限制较少的正则表达式的 JTextField,它们仍然显示我在构造函数中设置的值。为什么它会覆盖传递给构造函数的值,而不是传递给 setText() 的值?

最佳答案

不要使用PlainDocument,使用DocumentFilter,这就是它的设计目的。例如,您尝试使用的方法已经过时了 10 多年......

public class PatternFilter extends DocumentFilter {

    // Useful for every kind of input validation !
    // this is the insert pattern
    // The pattern must contain all subpatterns so we can enter characters into a text component !
    private Pattern pattern;

    public PatternFilter(String pat) {
        pattern = Pattern.compile(pat);
    }

    public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
            throws BadLocationException {

        String newStr = fb.getDocument().getText(0, fb.getDocument().getLength()) + string;
        Matcher m = pattern.matcher(newStr);
        if (m.matches()) {
            super.insertString(fb, offset, string, attr);
        } else {
        }
    }

    public void replace(FilterBypass fb, int offset,
                        int length, String string, AttributeSet attr) throws
            BadLocationException {

        if (length > 0) fb.remove(offset, length);
        insertString(fb, offset, string, attr);
    }
}

来自这个DocumentFilter Examples

看看Implementing a Document Filter了解更多详情

如果您不需要实时过滤,另一个选择是使用 JFormattedTextFieldJSpinner。请参阅How to Use Formatted Text FieldsHow to Use Spinners了解更多详情

关于java - 应用正则表达式的 JTextField 在应用文档之前不会接受值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28790820/

相关文章:

java - 多维数组java的行和列

java - JPanel 无法正确绘制

java - 获取paintComponent中多个绘图的位置

java - 如何通过指定命令行参数将字符串读入 Strings[] args?

为什么数学函数Math.round(0.49999999999999994) 返回 1

javascript - Return |\x0a 与其他的符号表示

javascript - Jquery - Chrome 和 Firefox 中的正则表达式按键操作不同

java - 一般在 SWING/Java 中使用线程的最佳实践

java - Array map() 期间令人困惑的隐式转换

regex - Sed 替换 URL 中的域