Search code examples
javaswingjtextfieldjoptionpane

JTextField and DefaultButton regarding ENTER key consumption


In the SSCCE bellow, I have a JTextField with a registered KeyListener. The KeyRelease function, will show a JOptionPane if the key is ENTER.

The problem is: if the user validates the JOptionPane using the ENTER key, the option pane will appear again! Seems the ENTER key is not consumed and forwarded to the JTextField.

Any clue ?

import java.awt.EventQueue;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

public class DefaultButtonAndTextFieldKeypress {
    private static void createGUI() {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        JTextField tf = new JTextField("Press ENTER");
        tf.addKeyListener(new KeyListener() {           
            @Override
            public void keyTyped(KeyEvent e) {}

            @Override
            public void keyReleased(KeyEvent e) {
                System.out.println("TextField::keyReleased");
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    JOptionPane.showMessageDialog(f, "Invalid input value, Press ENTER");
                }
            }

            @Override
            public void keyPressed(KeyEvent e) {}
        });

        f.add(tf);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                createGUI();
            }
        });
    }
}

Solution

  • This happens because dialog closes when keyPressed, but you open the dialog when keyReleased. Lets see how it runs with an example:

    1. You press Enteron text field, nothing happens.
    2. You RELEASE Enter, dialog pops up.
    3. You press Enter, dialog closes and text field gains focus.
    4. You release Enter, (because u had it pressed to close dialog), and dialog pops up again.

    I suggest you the following solution, when it comes to Enter press in a JTextField:

    tf.addActionListener(e -> {
        JOptionPane.showMessageDialog(f, "Invalid input value, Press ENTER");
    });
    

    Check it yourself and you will see it behaves perfect.

    Now, with if you want to use your key listener, it will require more effort in order to achieve it safely. Maybe a focus listener that recognizes when enter was not pressed in the text field at the first place (it was pressed on the dialog, but RELEASED on text field).

    I guess there are other workarounds too, but I suggest you to use the action listener.