Search code examples
javaswingkeylistenerkey-bindingsactionevent

Invoke a serie of actions when Enter key is pressed


I have one Swing project and I have an action listener on JTextField for Tab key as follows.

There is a JOptionPane.showMessageDialog() inside the action listener. And when Tab is pressed option pane will show an Information message.

My problem is that, when I press Enter on OK button of Information Message dialog, a serie of action is invoked viz Tab action of JTextField and Enter action of btnNewButton.

If I use mouse click on OK button of Error Message dialog, every thing is fine and no problem.

Can I solve this using key bindings instead of key listener?

Please suggest a solution

import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Collections;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

public class Test extends JFrame {
    private JPanel contentPane;
    private JTextField textField;
    private JButton btnNewButton;
    private JDialog dialog;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Test frame = new Test();
                    frame.setVisible(true);
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public Test() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        setLocationRelativeTo(null);
        contentPane.setLayout(null);

        textField = new JTextField();
        textField.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
                Collections.emptySet());
        textField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_TAB) {
                    JOptionPane.showMessageDialog(dialog, " Please Press ENTER Key", "information",
                            JOptionPane.INFORMATION_MESSAGE);

                    btnNewButton.grabFocus();
                }
            }
        });
        textField.setBounds(73, 28, 178, 28);
        contentPane.add(textField);
        textField.setColumns(10);

        btnNewButton = new JButton("New button");
        btnNewButton.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    JOptionPane.showMessageDialog(dialog, " That Invoked New Button Also", "Error",
                            JOptionPane.ERROR_MESSAGE);
                }
            }
        });
        btnNewButton.setBounds(223, 137, 117, 25);
        contentPane.add(btnNewButton);

        JLabel lblNewLabel = new JLabel("Please Press TAB Key");
        lblNewLabel.setBounds(83, 55, 183, 15);
        contentPane.add(lblNewLabel);

        dialog = new JDialog();
        dialog.setAlwaysOnTop(true);
    }
}

Solution

  • The problem is that you are overriding method keyReleased(). The JOptionPane is closing before the keyReleased() method is called and since you make btnNewButton the focused component after the JOptionPane is closed, the keyReleased() method is invoked – which displays the other JOptionPane.

    Simply rename the method to keyPressed().

    Also, you don't need the dialog member. The first parameter to JOptionPane#showMessageDialog should be the JFrame.

    Here is your code with my corrections.

    import java.awt.EventQueue;
    import java.awt.KeyboardFocusManager;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.util.Collections;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import javax.swing.border.EmptyBorder;
    
    public class Test extends JFrame {
        private JPanel contentPane;
        private JTextField textField;
        private JButton btnNewButton;
    
        /**
         * Launch the application.
         */
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    try {
                        Test frame = new Test();
                        frame.setVisible(true);
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    
        public Test() {
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setBounds(100, 100, 450, 300);
            contentPane = new JPanel();
            contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
            setContentPane(contentPane);
            setLocationRelativeTo(null);
            contentPane.setLayout(null);
    
            textField = new JTextField();
            textField.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
                    Collections.emptySet());
            textField.addKeyListener(new java.awt.event.KeyAdapter() {
                public void keyPressed(java.awt.event.KeyEvent evt) {
                    if (evt.getKeyCode() == KeyEvent.VK_TAB) {
                        JOptionPane.showMessageDialog(Test.this, " Please Press ENTER Key", "information",
                                JOptionPane.INFORMATION_MESSAGE);
                        btnNewButton.grabFocus();
                    }
                }
            });
            textField.setBounds(73, 28, 178, 28);
            contentPane.add(textField);
            textField.setColumns(10);
    
            btnNewButton = new JButton("New button");
            btnNewButton.addKeyListener(new KeyAdapter() {
                @Override
                public void keyPressed(KeyEvent e) {
                    if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                        JOptionPane.showMessageDialog(Test.this, " That Invoked New Button Also", "Error",
                                JOptionPane.ERROR_MESSAGE);
                    }
                }
            });
            btnNewButton.setBounds(223, 137, 117, 25);
            contentPane.add(btnNewButton);
    
            JLabel lblNewLabel = new JLabel("Please Press TAB Key");
            lblNewLabel.setBounds(83, 55, 183, 15);
            contentPane.add(lblNewLabel);
        }
    }
    

    Note that (at least in JDK 15) there is no need to explicitly set the default close operation for JFrame since the default is EXIT_ON_CLOSE