javaswingkey-bindingskeystrokes

Release KeyBinding with Meta Mask


I have a KeyBinding for my Java game, where I use the meta key and the Z key to move to the left.

i.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, 4), "Z");
m.put("Z", sprite_moveLeft);

How do I write the release form of this?

i.put(KeyStroke.getKeyStroke(???????), "rZ");
m.put("rZ", sprite_rmoveLeft);

I've already tried

i.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, 4), "Z");
m.put("Z", sprite_moveLeft);
i.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, 4, true), "rZ");
m.put("rZ", sprite_rmoveLeft);

but to no avail, and have tried changing the KeyEvents to keycodes (int).


Solution

  • Try using...

    KeyStroke.getKeyStroke(int keyCode, int modifiers, boolean onKeyRelease)
    

    Updated with working example

    public class KeyBindingsTest {
    
        public static void main(String[] args) {
            new KeyBindingsTest();
        }
    
        public KeyBindingsTest() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (Exception ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new KeyBindingPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public static class KeyBindingPane extends JPanel {
    
            private JTextArea textArea;
    
            public KeyBindingPane() {
                setLayout(new BorderLayout());
                add(new JScrollPane((textArea = new JTextArea())));
    
                InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
                ActionMap am = getActionMap();
    
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.ALT_DOWN_MASK, false), "Released");
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.ALT_DOWN_MASK, true), "Pressed");
    
                am.put("Released", new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        System.out.println("released");
                        textArea.append("Released\n");
                    }
                });
                am.put("Pressed", new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        System.out.println("pressed");
                        textArea.append("Pressed\n");
                    }
                });
    
                setFocusable(true);
                requestFocusInWindow();
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(100, 100);
            }
        }
    }
    

    Note, I've never seen KeyEvent.META_DOWN_MASK work on Windows...