I want the message box to appear immediately after the user changes the value in the textfield. Currently, I need to hit the enter key to get the message box to pop out. Is there anything wrong with my code?
textField.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if (Integer.parseInt(textField.getText())<=0){
JOptionPane.showMessageDialog(null,
"Error: Please enter number bigger than 0", "Error Message",
JOptionPane.ERROR_MESSAGE);
}
}
}
Any help would be appreciated!
Add a listener to the underlying Document, which is automatically created for you.
The usual answer to this is "use a
DocumentListener
". However, I always find that interface cumbersome. Truthfully the interface is over-engineered. It has three methods, for insertion, removal, and replacement of text, when it only needs one method: replacement. (An insertion can be viewed as a replacement of no text with some text, and a removal can be viewed as a replacement of some text with no text.)Usually all you want is to know is when the text in the box has changed, so a typical
DocumentListener
implementation has the three methods calling one method.Therefore I made the following utility method, which lets you use a simpler
ChangeListener
rather than aDocumentListener
. (It uses Java 8's lambda syntax, but you can adapt it for old Java if needed.)Unlike with adding a listener directly to the document, this handles the (uncommon) case that you install a new document object on a text component. Additionally, it works around the problem mentioned in Jean-Marc Astesana's answer, where the document sometimes fires more events than it needs to.
Anyway, this method lets you replace annoying code which looks like this:
With:
Code released to public domain. Have fun!
Use a KeyListener (which triggers on any key) rather than the ActionListener (which triggers on enter)
Just crate an interface that extends DocumentListener and implements all DocumentListener methods:
and then:
or you can even use lambda expression:
I know this relates to a really old problem, however, it caused me some problems too. As kleopatra responded in a comment above, I solved the problem with a
JFormattedTextField
. However, the solution requires a bit more work, but is neater.The
JFormattedTextField
doesn't by default trigger a property change after every text changes in the field. The default constructor ofJFormattedTextField
does not create a formatter.However, to do what the OP suggested, you need to use a formatter which will invoke the
commitEdit()
method after each valid edit of the field. ThecommitEdit()
method is what triggers the property change from what I can see and without the formatter, this is triggered by default on a focus change or when the enter key is pressed.See http://docs.oracle.com/javase/tutorial/uiswing/components/formattedtextfield.html#value for more details.
Create a default formatter (
DefaultFormatter
) object to be passed to theJFormattedTextField
either via its constructor or a setter method. One method of the default formatter issetCommitsOnValidEdit(boolean commit)
, which sets the formatter to trigger thecommitEdit()
method every time the text is changed. This can then be picked up using aPropertyChangeListener
and thepropertyChange()
method.But I would not just parse anything the user (maybe on accident) touches on his keyboard into an
Integer
. You should catch anyException
s thrown and make sure theJTextField
is not empty.