4

How could I use key bindings in this code as key adapter doesn't work well? I already looked at the documentation of key binding but I can't understand how to do this.

private class KeyLis extends KeyAdapter 
{   
    @Override
    public void keyPressed(KeyEvent e) 
    {
        switch (e.getKeyCode())
        {
        case KeyEvent.VK_UP:
            up = true;
            break;
        case KeyEvent.VK_DOWN:
            down = true;
            break;
        case KeyEvent.VK_LEFT:
            left = true;
            break;
        case KeyEvent.VK_RIGHT:
            right = true;
            break;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) 
    {
        switch (e.getKeyCode())
        {
        case KeyEvent.VK_UP:
            up = false;
            break;
        case KeyEvent.VK_DOWN:
            down = false;
            break;
        case KeyEvent.VK_LEFT:
            left = false;
            break;
        case KeyEvent.VK_RIGHT:
            right = false;
            break;
        }
    }
}

Thank you

mKorbel
  • 109,525
  • 20
  • 134
  • 319
sanchixx
  • 275
  • 2
  • 5
  • 12

1 Answers1

4

You need to add the respective key to the InputMap of the component on which to apply KeyBinding as shown here :

panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
    KeyStroke.getKeyStroke("pressed UP"), "pressedUPAction");
panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
    KeyStroke.getKeyStroke("released UP"), "releasedUPAction");

panel.getActionMap().put("pressedUPAction", new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent ae) {
        System.out.println("UP Arrow Pressed");
    }
});

panel.getActionMap().put("releasedUPAction", new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent ae) {
        System.out.println("UP Arrow Released");
    }
});

Have a look at this working example :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class SmallExample {

    private JButton button;
    private JPanel panel;

    private void displayGUI() {
        JFrame frame = new JFrame("Small Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        panel = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return (new Dimension(100, 100));
            }
        };
        panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke("pressed UP"), "pressedUPAction");
        panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke("released UP"), "releasedUPAction");

        panel.getActionMap().put("pressedUPAction", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                System.out.println("UP Arrow Pressed");
            }
        });

        panel.getActionMap().put("releasedUPAction", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                System.out.println("UP Arrow Released");
            }
        });

        frame.setContentPane(panel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new SmallExample().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
  • 1
    nitpicking: componentInputMaps (aka: those of type when-in-focused-window) should be used with extreme care, read: rarely :-) – kleopatra Aug 04 '13 at 16:52
  • @kleopatra : LOL, no doubt, I am about to learn something new today. Please elaborate :-) – nIcE cOw Aug 04 '13 at 16:54
  • 1
    a) they are the last to be asked b) it's unpredictable which binding gets used if there are duplicates in the window c) they can't be shared across instances – kleopatra Aug 04 '13 at 16:57
  • @kleopatra : So where may I find something to look what exactly I can do, in place of `WHEN_IN_FOCUSED_WINDOW`. Is there any tutorial, too regarding the same. Since I read from where the OP read it, and I guess they failed to mention these points !!! LOL, how come you know such minute details, please do tell me this secret too :-) – nIcE cOw Aug 04 '13 at 16:59
  • typically, when-ancestor is the most appropriate (where you get whatever the children don't handle yourself). Remember it being explained in the original design article about keybindings (old swing connection?), don't know where to find it or where else to look if it's not in the tutorial – kleopatra Aug 04 '13 at 17:05
  • @kleopatra : Yeah, I found a line that says __"The WHEN_IN_FOCUSED_WINDOW input maps of all the enabled components in the focused window are searched. Because the order of searching the components is unpredictable, avoid duplicate WHEN_IN_FOCUSED_WINDOW bindings!"__ , so putting more effort to find more information on this topic :-) Will experiment a little with `KeyBinding` in coming days. I added that to my `To-Do-List` :-) – nIcE cOw Aug 04 '13 at 17:11
  • 1
    +1 yes and not, everything depends of focus, focus owner and if is focusable only, for example add focus to JButton in the JFrame, JPanel (you can to moving with focus aroung all types of JComponents works with all types ...) is very different as firing ENTER key from JTextField(implemented in API) – mKorbel Aug 04 '13 at 17:15
  • @sanchixx : Please try to use `JComponent.WHEN_FOCUSED`, in place of `JComponent.WHEN_IN_FOCUSED_WINDOW`, as much as possible. – nIcE cOw Aug 04 '13 at 17:15
  • @mKorbel : Half of the comment went over my head, though I understood the first half :-) – nIcE cOw Aug 04 '13 at 17:18