我希望程序中的一些JTextField
只接受与特定Pattern
匹配的新输入。
我知道JFormattedTextField
的面具,不我想要的东西。
对于每个新输入,如果这些更改符合特定正则表达式模式的流程,则文本应仅接受更改。
这必须通过正则表达式完成,因为“正则表达式要求”的情况,比如输入应该接收自身的一部分。通过一个例子可以更好地理解这一点:
假设我的正则表达式为"(\\d{2})-bk\\d{3}\\.\\1"
。
输入"123-bk001."
时,下一个输入的字符必须等于第一组,这意味着只有3个输入字符分别等于123
才能被接受。
输入“456-bk404”。将要求下一个字符为"456"
。
我该怎么做?
这个例子只是为了说明没有正则表达式难以解决的情况之一,我的实际用途不仅限于此。所以,如果可能的话,答案应该是更广泛的可用性(从问题的角度来看),而不是具体到这个例子。
但是,如果不可能或者为少数(3-5个)不同案例实施特定解决方案会更难,请随时告诉。
答案 0 :(得分:2)
使用DocumentFilter
删除或替换已定义的不需要的字符(可能可以使用NavigationFilter.Bias
)
您可以定义自己的InputMask
with InputVerifier
答案 1 :(得分:0)
我的直觉方法是使用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);
}
}