Search code examples
javaswingawtkey-bindings

How to get the press and release event of a specified key?


I want to know when users press a specified key like ctrl, shift or other keys and when users release it.

I have used Key Binding for a JPanel and I can know when users type a specified key.The code is below:

 import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;

    import javax.swing.AbstractAction;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.KeyStroke;


    public class KeyBindingTest {
        public static void main(String[] args) {
            KeyBindingTest test = new KeyBindingTest();
            test.createUI();
        }

        public void createUI(){
            JFrame frame = new JFrame("KeyBinding Test");
            MainPanel mainPanel = new MainPanel();
            frame.add(mainPanel,BorderLayout.CENTER);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }

        @SuppressWarnings("serial")
        class MainPanel extends JPanel{
            public MainPanel(){
                setPreferredSize(new Dimension(200, 200));
                //========================key binding============================
                requestFocusInWindow();
                String ctrlString = "ctrlStr";
                getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, KeyEvent.CTRL_DOWN_MASK), ctrlString);
                getActionMap().put(ctrlString, new AbstractAction() {           
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        // TODO Auto-generated method stub
                        System.out.println("ctrl is typed");
                    }
                });         
            }   
        }
    }

Thanks for your help in advance.


Solution

  • You can use these variants of KeyStroke Class, KeyStroke.getKeyStroke(int, int, boolean) and KeyStroke.getKeyStroke(String), to get the desired result.

    For pressed CTRL, use the following:

    KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, InputEvent.CTRL_DOWN_MASK, false);
    

    For released CTRL, use the following:

    keyStroke = KeyStroke.getKeyStroke("released CONTROL");
    

    Here try this program:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class KeyExample {
    
        private JPanel contentPane;
    
        private class KeyAction extends AbstractAction {
    
            private String keyState;
            private String keyValue;
    
            public KeyAction(String state, String value) {
                this.keyState = state;
                this.keyValue = value;
            }
    
            @Override
            public void actionPerformed(ActionEvent ae) {
                System.out.println("Value: " + keyValue + " State: " + keyState);
            }
        }
    
        private void displayGUI() {
            JFrame frame = new JFrame("Swing Worker Example");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    
            contentPane = new JPanel();
            InputMap inputMap = contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
    
            KeyStroke keyStroke = null;
    
            keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, InputEvent.CTRL_DOWN_MASK, false);
            inputMap.put(keyStroke, "pressedControl");
            contentPane.getActionMap().put("pressedControl", new KeyAction("pressed", "CONTROL"));
    
            keyStroke = KeyStroke.getKeyStroke("released CONTROL");
            inputMap.put(keyStroke, "releasedControl");
            contentPane.getActionMap().put("releasedControl", new KeyAction("released", "CONTROL"));
    
            keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_SHIFT, InputEvent.SHIFT_DOWN_MASK, false);
            inputMap.put(keyStroke, "pressedShift");
            contentPane.getActionMap().put("pressedShift", new KeyAction("pressed", "SHIFT"));
    
            keyStroke = KeyStroke.getKeyStroke("released SHIFT");
            inputMap.put(keyStroke, "releasedShift");
            contentPane.getActionMap().put("releasedShift", new KeyAction("released", "SHIFT"));
    
            keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ALT, InputEvent.ALT_DOWN_MASK, false);
            inputMap.put(keyStroke, "pressedAlt");
            contentPane.getActionMap().put("pressedAlt", new KeyAction("pressed", "ALT"));
    
            keyStroke = KeyStroke.getKeyStroke("released ALT");
            inputMap.put(keyStroke, "releasedAlt");
            contentPane.getActionMap().put("releasedAlt", new KeyAction("released", "ALT"));
    
            frame.setContentPane(contentPane);
            frame.setSize(300, 100);
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    new KeyExample().displayGUI();
                }
            };
            EventQueue.invokeLater(runnable);
        }
    }
    

    EDIT: 2

    Actually, that is what I am trying to do since yesterday, ever since I answered this. But seems like they do block in that implementation, though if I add a some another key in conjunction with CTRL and SHIFT, then it works fine. As stated in this snippet below:

    keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK, false);
            inputMap.put(keyStroke, "pressedControlShift");
            contentPane.getActionMap().put("pressedControlShift", new KeyAction("pressed", "CONTROL SHIFT"));