-1

I have a Jtextfield named tPvv, wrote a DocumentFilter for accept only numbers, maximum length of 3.And I have a button edit, when I click that button the entire row loaded in textfield's for editing from the jtable(value in Jtextfield tPvv remains constant). The Jtextfield which are defined without documentFilter works well(loads values from jtable to the textfields based on row selection). Also when I comment the DocumentFilter it works well, but I cannot provide the validation (accept number only and the length of 3).

I need to check the validation for the tPvv and also load the values from the jtable based on different row selection by clicking the edit button.

`class NumericAndLengthFilter extends DocumentFilter {

        /**
         * Number of characters allowed.
         */
        private int length = 0;

        /**
         * Restricts the number of charcacters can be entered by given length.
         * @param length Number of characters allowed.
         */
        public NumericAndLengthFilter(int length) {
            this.length = length;
        }

        @Override
        public void insertString(FilterBypass fb, int offset, String string,
                AttributeSet attr) throws
                BadLocationException {
            if (isNumeric(string)) {
                if (this.length > 0 && fb.getDocument().getLength() + string.
                        length()
                        > this.length) {
                    return;
                }
                super.insertString(fb, offset, string, attr);
            }
        }

        @Override
        public void replace(FilterBypass fb, int offset, int length, String text,
                AttributeSet attrs) throws
                BadLocationException {
            if (isNumeric(text)) {
                if (this.length > 0 && fb.getDocument().getLength() + text.
                        length()
                        > this.length) {
                    return;
                }
                super.insertString(fb, offset, text, attrs);
            }
        }

        /**
         * This method tests whether given text can be represented as number.
         * This method can be enhanced further for specific needs.
         * @param text Input text.
         * @return {@code true} if given string can be converted to number; otherwise returns {@code false}.
         */
        private boolean isNumeric(String text) {
            if (text == null || text.trim().equals("")) {
                return false;
            }
            for (int iCount = 0; iCount < text.length(); iCount++) {
                if (!Character.isDigit(text.charAt(iCount))) {
                    return false;
                }
            }
            return true;
        }

}
//((AbstractDocument) tPvv.getDocument()).setDocumentFilter(new NumericAndLengthFilter(3));

`last commented line i defined in my code for the validation purpose call. Please solve this problem.

StanislavL
  • 56,971
  • 9
  • 68
  • 98
aarav
  • 230
  • 1
  • 4
  • 21
  • For a textfield only accepting numbers (even with a limited length), you can also take a look at [this question](http://stackoverflow.com/a/13424140/1076463) – Robin Sep 04 '13 at 19:50

1 Answers1

3

You're basically ignoring the parameters that are passed to you and what they mean...

  • offset is the offset within the document where the new text will be inserted...
  • length is the number of characters to be deleted

Now, if we use the length within the if statement, we start to see a difference. Basically, when you call setText, the length will be equal to the number of characters in the text field (as all the text is to be replaced)...

public void replace(FilterBypass fb, int offset, int length, String text,
                AttributeSet attrs) throws
                BadLocationException {
    if (isNumeric(text)) {

        System.out.println(offset + "; " + length + "; " + text);

        if (this.length > 0 && 
            fb.getDocument().getLength() + text.length() - length > this.length) {
            return;
        }
        super.replace(fb, offset, length, text, attrs);
    }
}

You're also calling super.insertString(fb, offset, text, attrs); in the replace method, which isn't helpful either...

Update from comments

The problem you're facing with setText(null) is to do with the fact that isNumeric in your filter is returning false for null and empty ("") values, but these are actually valid in some contexts...

Now, you could alter the isNumeric method, but that might adversely affect the other methods of the filter, instead, we should be place an additional condition in replace to catch this case and deal with it appropriately...

public void replace(FilterBypass fb, int offset, int length, String text,
                AttributeSet attrs) throws
                BadLocationException {
    if (isNumeric(text)) {

        System.out.println(offset + "; " + length + "; " + text);

        if (this.length > 0 && 
            fb.getDocument().getLength() + text.length() - length > this.length) {
            return;
        }
        super.replace(fb, offset, length, text, attrs);
    } else if (text == null || text.equals("")) {
        super.replace(fb, offset, length, text, attrs);
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • above code solves mentioned problem, but new problem arise, when I click add button all the text fields become empty or blank (i called Textfield.setText(null)method)but the value in the tPvv(Docfilter created for this JTextField) textfield cotnents not removed. – aarav Sep 04 '13 at 09:41
  • *"i called Textfield.setText(null)"*, yet in your `isNumeric` you return `false` for values that are equal to `null` and empty. I would return consider returning `true`, but you'll need to add extra checks in for `null` `String`s in your other methods. Alternatively, add `else if` statement to you `replace` method to includes the possibility of a `null` `String` and call `super.replace(...)` – MadProgrammer Sep 04 '13 at 10:02