javaswingdocumentlistenerdocumentfilter

jtextfield documentFilter once defined, value not loading in the jtextfield


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.


Solution

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

    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);
        }
    }