-1

Is it possible to use a single DocumentFilter to limit both the allowed characters and the number of characters in a JTextField? I don't get how to do both and I didn't find any fully working workaround.

kleopatra
  • 51,061
  • 28
  • 99
  • 211
Korenji
  • 19
  • 4
  • Yes, see [How To limit the number of characters in JTextField?](https://stackoverflow.com/questions/3519151/how-to-limit-the-number-of-characters-in-jtextfield) and combine it with this answer: [Allow only numbers in JTextfield](https://stackoverflow.com/questions/20541230/allow-only-numbers-in-jtextfield) just change it to work with the character types you want. – sorifiend Jul 14 '22 at 00:24
  • The first question is solved using setDocument() with a PlainDocument, the second one actually uses a DocumentFilter. Anyway, I tried to set both the document using JTextField#setDocument and the document filter through setDocumentFilter() on the AbstractDocument obtained from JTextField#getDocument, but the second instruction I wrote overwrites the first one. In other words, I cannot set both a PlainDocument and a DocumentFilter this way. – Korenji Jul 14 '22 at 00:40
  • 1
    You need to combine both answers into a single document and set it once. A PlainDocument is a Subclasses of AbstractDocument, so in the first example that extends a PlainDocument you can also override the replace method and any other methods of the Abstract/PlainDocument as shown here https://stackoverflow.com/questions/11093326/restricting-jtextfield-input-to-integers Or you can just override an AbstractDocument and implement the limit in there instead. And when you set the document you only need to sit it once for example `yourTextField.setDocument(new yourCustomDocument(textLimit));` – sorifiend Jul 14 '22 at 01:01
  • @sorifiend That's what I was trying to do, but I cannot grasp how to correctly override that method. My only result for now is a `JTextField` that doubles any inserted valid character, lets write once the banned ones and is able to exceed the text limit. – Korenji Jul 14 '22 at 02:44

1 Answers1

1

Ok, I finally get how it works! I needed to use ifs in replace() method, because that's the code that gets called everytime the user inputs/pastes anything in the JTextField:

  1. if the already inserted text length (fb.getDocument().getLength()) summed to the user current input/paste (text.length()) is greater than the intended limit (I setted it to 12 characters), first delete any invalid characters from the user input (text.replaceAll(regex, "")) and then truncate it so that it does not exceed the limit;
  2. otherwise, if the text would not exceed the limit, just delete any possible invalid characters.

 

class NameFilter extends DocumentFilter {
    @Override
    public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
        int finalLength = fb.getDocument().getLength() + text.length();

        if(finalLength > 12) {
            fb.replace(offset, length, text.replaceAll("[^a-zA-Z0-9/&\\-':;.,?!@]", "").substring(0, 12-fb.getDocument().getLength()), attrs);
            Toolkit.getDefaultToolkit().beep();
        } else
            fb.replace(offset, length, text.replaceAll("[^a-zA-Z0-9/&\\-':;.,?!@]", ""), attrs);
    }
}
Korenji
  • 19
  • 4