Posted by Rob Camick on December 15, 2008
A common requirement is to validate text as it is being typed into a text component. Unfortunately a common solution suggested in the forums is to use a KeyListener
and to override the keyTyped() event. Using this approach the event is consumed when an invalid character is entered to prevent the character from being added to the Document. This approach can work in certain situations, however, JDK1.4 introduced a couple of new features that provide better, more complete, solutions than are available when using a KeyListener.
First we need to address the problems of using a KeyListener:
- single characters – this approach will only handle the input of a single typed character, therefore you tend to write your code to only edit a single character at a time.
- pasting text (Ctrl+V) – first of all chances are your code won’t handle the pasting of multiple characters (see above), but even if it did, there is no way to get all the characters pasted because the KeyEvent doesn’t have this information. Secondly, it doesn’t matter that you can’t get the pasted text because there is no way to prevent the pasted text from automatically being inserted into the Document.
- paste Action – maybe you have a menu item or a toolbar button to paste text. Well, in this case a KeyEvent isn’t even generated, so therefore this approach will never work
Hopefully, I’ve explained the limitations of using a KeyListener. So what are the alternatives? Well, I can think of at least two better approaches. These approaches will work no matter how the text is added to the Document. That is they will support typing, pasting and Actions.
- JFormattedTextField – a component designed to handle many validation requirements. You can do basic editing for letters, numbers, dates or control the number of characters that can be entered.
- DocumentFilter – all text to be inserted into a Document must first pass through the DocumentFilter. This means whether it was typed, pasted or added by an Action the filter will be invoked. Not only can you prevent text from being entered into the Document, you can even change the text dynamically. For example, you could converting all lower cased text to upper case. Or, you could replace entered text with a smiley icon. You have access to the entire Document, not just the text being entered.
The formatted text field is the easiest to use for simple editing, but the DocumentFilter gives you ultimate control. Read the links provide below for more information and examples on both of these approaches.
Another type of text validation is to validate the entire content of the text component for completeness. For example, you should probably verify that the year, month and day are entered to give a complete date. This type of validating might be done by using a FocusListener to handle the focusLost event. However, as of JDK1.3 a better approach can be used. That would be to use an InputVerifier. The InputVerifier is invoked when the text component loses focus, but the good part is that focus is returned to the text component if the validation code you invoke fails. Check out the tutorial link below for a better explanation and a working example.