Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Value Change Listener to JTextField

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!

like image 899
user236501 Avatar asked Oct 17 '10 12:10

user236501


People also ask

What is the default value of JTextField?

If the initial text is not specified, its default value is null (the text field is empty). If the number of columns is not specified, its default value is 0 (then the text field's width is calculated based on the initial text).

What happens if you press Enter in JTextField?

Now the event is fired when the Enter key is used. Also, an added benefit is that you can share the listener with a button even if you don't want to make the button a default button. JButton button = new JButton("Do Something"); button.

How do you use listener change?

In short, to use a simple ChangeListener one should follow these steps: Create a new ChangeListener instance. Override the stateChanged method to customize the handling of specific events. Use specific functions of components to get better undemanding of the event that occurred.

What is difference between JTextArea and JTextField?

The main difference between JTextField and JTextArea in Java is that a JTextField allows entering a single line of text in a GUI application while the JTextArea allows entering multiple lines of text in a GUI application.


2 Answers

Add a listener to the underlying Document, which is automatically created for you.

// Listen for changes in the text textField.getDocument().addDocumentListener(new DocumentListener() {   public void changedUpdate(DocumentEvent e) {     warn();   }   public void removeUpdate(DocumentEvent e) {     warn();   }   public void insertUpdate(DocumentEvent e) {     warn();   }    public void warn() {      if (Integer.parseInt(textField.getText())<=0){        JOptionPane.showMessageDialog(null,           "Error: Please enter number bigger than 0", "Error Message",           JOptionPane.ERROR_MESSAGE);      }   } }); 
like image 111
Codemwnci Avatar answered Sep 23 '22 02:09

Codemwnci


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 a DocumentListener. (It uses Java 8's lambda syntax, but you can adapt it for old Java if needed.)

/**  * Installs a listener to receive notification when the text of any  * {@code JTextComponent} is changed. Internally, it installs a  * {@link DocumentListener} on the text component's {@link Document},  * and a {@link PropertyChangeListener} on the text component to detect  * if the {@code Document} itself is replaced.  *   * @param text any text component, such as a {@link JTextField}  *        or {@link JTextArea}  * @param changeListener a listener to receieve {@link ChangeEvent}s  *        when the text is changed; the source object for the events  *        will be the text component  * @throws NullPointerException if either parameter is null  */ public static void addChangeListener(JTextComponent text, ChangeListener changeListener) {     Objects.requireNonNull(text);     Objects.requireNonNull(changeListener);     DocumentListener dl = new DocumentListener() {         private int lastChange = 0, lastNotifiedChange = 0;          @Override         public void insertUpdate(DocumentEvent e) {             changedUpdate(e);         }          @Override         public void removeUpdate(DocumentEvent e) {             changedUpdate(e);         }          @Override         public void changedUpdate(DocumentEvent e) {             lastChange++;             SwingUtilities.invokeLater(() -> {                 if (lastNotifiedChange != lastChange) {                     lastNotifiedChange = lastChange;                     changeListener.stateChanged(new ChangeEvent(text));                 }             });         }     };     text.addPropertyChangeListener("document", (PropertyChangeEvent e) -> {         Document d1 = (Document)e.getOldValue();         Document d2 = (Document)e.getNewValue();         if (d1 != null) d1.removeDocumentListener(dl);         if (d2 != null) d2.addDocumentListener(dl);         dl.changedUpdate(null);     });     Document d = text.getDocument();     if (d != null) d.addDocumentListener(dl); } 

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:

someTextBox.getDocument().addDocumentListener(new DocumentListener() {     @Override     public void insertUpdate(DocumentEvent e) {         doSomething();     }      @Override     public void removeUpdate(DocumentEvent e) {         doSomething();     }      @Override     public void changedUpdate(DocumentEvent e) {         doSomething();     } }); 

With:

addChangeListener(someTextBox, e -> doSomething()); 

Code released to public domain. Have fun!

like image 26
Boann Avatar answered Sep 23 '22 02:09

Boann