应用正则表达式的 JTextField 在应用文档之前不会接受值
JTextField with regex applied won't accept value until AFTER the Document is applied
我有一个 JTextField,我已经覆盖了它的文档,这样我就可以防止用户输入一些字符。它的工作方式是我的 Document 扩展在其构造函数中接收一个 Regex,然后根据 Regex 检查用户键入的任何内容:
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");
}
}
}
但是我遇到了一个问题,我只想在其中显示有效 float/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);
正如我所怀疑的那样,它包含字母字符,尽管 Regex 应该阻止它。所以我的想法是在使用此功能时绕过文档。
谁能阐明为什么将 ValidDocument 应用于我的 JTextField 会删除我放置在文本字段构造函数中的文本?我还有其他 JTextFields,它们的正则表达式限制较少,但仍然显示我在构造函数中设置的值。为什么它会覆盖传递给构造函数的值,而不是传递给 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);
}
}
查看 Implementing a Document Filter 了解更多详情
如果您不需要实时过滤,另一种选择是使用 JFormattedTextField
或 JSpinner
。有关详细信息,请参阅 How to Use Formatted Text Fields and How to Use Spinners
我有一个 JTextField,我已经覆盖了它的文档,这样我就可以防止用户输入一些字符。它的工作方式是我的 Document 扩展在其构造函数中接收一个 Regex,然后根据 Regex 检查用户键入的任何内容:
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");
}
}
}
但是我遇到了一个问题,我只想在其中显示有效 float/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);
正如我所怀疑的那样,它包含字母字符,尽管 Regex 应该阻止它。所以我的想法是在使用此功能时绕过文档。
谁能阐明为什么将 ValidDocument 应用于我的 JTextField 会删除我放置在文本字段构造函数中的文本?我还有其他 JTextFields,它们的正则表达式限制较少,但仍然显示我在构造函数中设置的值。为什么它会覆盖传递给构造函数的值,而不是传递给 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);
}
}
查看 Implementing a Document Filter 了解更多详情
如果您不需要实时过滤,另一种选择是使用 JFormattedTextField
或 JSpinner
。有关详细信息,请参阅 How to Use Formatted Text Fields and How to Use Spinners