Reputation: 3592
I am trying to create Java IMEI checksum calculator. The checksum is the last digit in the IMEI 15 digits.
Therefore, I need to create JTextField which limit to 14 characters and also restricted to digits only!
For the 14 characters limitation I've made a class extends PlainDocument as follow:
public final class LengthRestrictedDocument extends PlainDocument {
private final int limit;
public LengthRestrictedDocument(int limit) {
this.limit = limit;
}
public void insertString(int offs, String str, AttributeSet a)
throws BadLocationException {
if (str == null)
return;
if ((getLength() + str.length()) <= limit) {
super.insertString(offs, str, a);
}
}
}
Then I applied it to the JTextField like this:
PlainDocument document = new LengthRestrictedDocument(14);
tfImei.setDocument(document); //Restricting inputs to 14 digits
For the digits only I've tried to use DocumentFilter like this:
DocumentFilter docFilter = new DocumentFilter() {
Pattern regEx = Pattern.compile("\\d+");
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
Matcher matcher = regEx.matcher(text);
if (!matcher.matches()) {
return;
}
super.replace(fb, offset, length, text, attrs);
}
};
I am using it as follow:
PlainDocument document = new LengthRestrictedDocument(14);
document.setDocumentFilter(docFilter);
tfImei.setDocument(document); //Restricting inputs to 14 digits
it do the job for the digits only but it cancel the 14 digits limitation.
Can someone help to impliment such functionality? Restrict to 14 charachters and digits only?
Upvotes: 1
Views: 1065
Reputation: 3592
Finally I've got this to work! Yes, I've used Document Filter as following:
DocumentFilter docFilter = new DocumentFilter() {
Pattern regEx = Pattern.compile("\\d+");
final int maxCharLength = 14;
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
Matcher matcher = regEx.matcher(text);
if ((fb.getDocument().getLength() + text.length()) <= maxCharLength && matcher.matches()) {
super.replace(fb, offset, length, text, attrs);
}else{
Toolkit.getDefaultToolkit().beep();
}
}
};
AbstractDocument absDoc = (AbstractDocument)tfImei.getDocument();
absDoc.setDocumentFilter(docFilter);
This will filter to digits only and with length of 14!
Upvotes: 1
Reputation: 324108
For the 14 characters limitation I've made a class extends PlainDocument as follow:
This is an older approach. The newer approach is to use a DocumentFilter. Check out the section from the Swing tutorial on Implementing a DocumentFilter for a working example.
For the digits only I've tried to use DocumentFilter like this. it do the job for the digits only but it cancel the 14 digits limitation.
Don't use a custom Document and a DocumentFilter.
Instead you can combine the functionality into a single DocumentFilter.
Or for an even simpler solution you can use a JFormattedTextField
. You can specify a mask that controls the number of digits and the type of each digit:
MaskFormatter format = new MaskFormatter( "##############" );
JFormattedTextField ftf = new JFormattedTextField( mf );
The tutorial has a section on How to Use Text Fields
for more information and examples.
For a more flexible approach you may want to look at Chaining Document Filters. It allows you to combine multiple DocumentFilters into one filter so if any edit fails the insertion is prevented. This allows you to create reusable filters that you can use in different situations.
Upvotes: 2