Moti Bartov
Moti Bartov

Reputation: 3592

Java JTextField Length and filter

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

Answers (2)

Moti Bartov
Moti Bartov

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

camickr
camickr

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

Related Questions