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.
Asked
Active
Viewed 173 times
-1
-
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
-
1You 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 Answers
1
Ok, I finally get how it works! I needed to use if
s in replace()
method, because that's the code that gets called everytime the user inputs/pastes anything in the JTextField
:
- 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; - 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
-
@kleopatra I was just editing the answer. Now that should be just the right solution I was looking for! – Korenji Jul 14 '22 at 05:07
-