Search code examples
javaswingkey-bindingsjcomponent

Java KeyBindings not reacting on JPanel


I have previously used Java's KeyListener, but as my programs are demanding more I have gotten the recommendation to switch over to KeyBinds.

First of all I have tried to add keybindings to JFrame which didn't work ( I don't understand what JComponent I need to use. ). Therefore I tried moving the program over to a JPanel and then adding it to a JFrame, however the Key bind do not react when the desired button is pressed (in this case it's the "1" button);

In the method call I have set the action to be Print "Hi". Here is the code:

public class Panel extends javax.swing.JPanel {
JPanel Panel = new JPanel();
/**
 * Creates new form Panel
 */
public Panel() {
      addKeyBinding(Panel, KeyEvent.VK_1, "1Button", (evt)->{
          System.out.println("Hi");
    });
    initComponents();
}

..... And here is the method .....

public static void addKeyBinding(JComponent comp, int keyCode, String id, ActionListener actionListener){

    InputMap im = comp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
    ActionMap ap = comp.getActionMap();

    im.put(KeyStroke.getKeyStroke(keyCode, 0, false),
        id);

        ap.put(id, new AbstractAction(){
                @Override
                public void actionPerformed(ActionEvent e) {
                    actionListener.actionPerformed(e);
                }

    });

}

What am I doing wrong? Thanks!


Solution

  • The key bindings are for your form panel, right? I think you're misunderstanding a few concepts about classes and objects. Also it's hard to help without seeing the full code. But your error is very likely caused by this line:

    addKeyBinding(Panel, KeyEvent.VK_1, "1Button", ...
    

    which should be:

    addKeyBinding(this, KeyEvent.VK_1, "1Button", ...
    

    The variable Panel should be replaced with the keyword this thus referencing the actual form panel.

    It also should be created wherever you're creating your window so this line can also be removed:

    JPanel Panel = new JPanel();
    

    There are many things wrong with your code. I can't imagine the code in the first snippet even compiles. You are trying to name a variable the same as your classname.

    Your class has no reason to extend JPanel since it isn't a new type of JPanel. Simply remove your extends. Then change the first line to:

    JPanel panel = new JPanel();
    

    Then pass lower-case panel to the addKeyBinding method.

    If for some strange reason you want to keep your class extending JPanel then pass this as the first parameter to addKeyBinding as /u/tiiv said and remove the JPanel Panel = new JPanel line since that isn't needed (as you have it written now your class is the JPanel).

    As far as which component to use JFrame is a top-level container so that is usually your main application window. And then you put JPanel and other components in the JFrame. There are actually 4 top-level containers in swing (JFrame, JWindow, JDialog, and JApplet) but JFrame is generally the one you will use as your main app window.

    I hope that helps.