Search code examples
javajtextfielddocumentfilter

Making JTextField accept mixed String , whet documentFIlter alow only digits


I have unusual issue something is working a bit to well. I have written a DocumentFilter witch allow user input only as numbers, DocumentFilter add dash on it's own in proper place during writing. This way inJTextField is visible date like this is: "2016-05-01". The problem is that JTextField is not always filled in by user, sometimes it must be set by program. But when I use code setText("2016-05-01"), it don't display properly, all dash are gone. How to make it work ? I tried to change DocumentFilter to allow dash, but this why cause problems in many other places. I probably will end up writting another DocumentFilter just for this but maybe there is a other way? Is it possible to append JTextField char by char ? Is there a way to switch on an off the DocumentFilter, or mayby it's posible to change smartly DocumentFilter so it will not crush in oder palces and work here as well? Below part of code for DocumentFilter

  public void replace(FilterBypass fb, int offs, int length, String str,
    AttributeSet a) throws BadLocationException {

if (str == null || str.equals(""))
{
    super.replace(fb, offs, length, str, a); 
}
else
{
    StringBuffer buffer = new StringBuffer(str);
    for (int i = buffer.length() - 1; i >= 0; i--)
    {
    char ch = buffer.charAt(i);
    if (!Character.isDigit(ch))
    {
        buffer.deleteCharAt(i);
    }
    }

    str = buffer.toString();
    //sign and sign2 is char number were separator(sep) is written 
    if (fb.getDocument().getLength() + str.length() == sign)
    {
    str = str + sep;
    }
    if (fb.getDocument().getLength() + str.length() == sign2)
    {
    str = str + sep;
    }


    if ((fb.getDocument().getLength() + str.length() - length) <= maxCharacters)
    super.replace(fb, offs, length, str, a);
    else
    Toolkit.getDefaultToolkit().beep();
}

Solution

  • You can do something like this:

    @Override
    public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a) throws BadLocationException {
        if (str == null || str.equals("")) {
            super.replace(fb, offs, length, str, a);
        } else {
            // check if 'str' contains 8 digits
            if (str.matches("^\\d{8}$")) {
                // add the dashes
                super.replace(fb, offs, length, str.replaceAll("(\\d{4})(\\d{2})(\\d{2})", "$1-$2-$3"), a);
            } else {
                StringBuffer buffer = new StringBuffer(str);
                for (int i = buffer.length() - 1; i >= 0; i--) {
                    char ch = buffer.charAt(i);
                    if (!Character.isDigit(ch)) {
                        buffer.deleteCharAt(i);
                    }
                }
    
                str = buffer.toString();
                // sign and sign2 is char number were separator(sep) is written
                if (fb.getDocument().getLength() + str.length() == sign) {
                    str = str + sep;
                }
                if (fb.getDocument().getLength() + str.length() == sign2) {
                    str = str + sep;
                }
    
                if ((fb.getDocument().getLength() + str.length() - length) <= maxCharacters)
                    super.replace(fb, offs, length, str, a);
                else
                    Toolkit.getDefaultToolkit().beep();
            }
        }
    }
    

    and set the text using this:

    textField.setText("20160420");