Java KeyListener not responding after switching JPanels

对着背影说爱祢 提交于 2019-12-12 03:40:17

问题


I got a problem with the KeyListener not responding(due to not gaining focus) when I switch between JPanels.

I have Google'd this and know that to fix this problem I need to use KeyBindings, but I don't like KeyBindings. So I was wondering, is there any other way?

Here is the init code of the JPanel that has an unresponsive KeyListener:

    public void init()
{
    setFocusable(true);
    requestFocusInWindow();
    requestFocus();
    addMouseListener(new MouseInput());
    addMouseMotionListener(new MouseInput());
    addMouseWheelListener(new MouseInput());
    addKeyListener(new KeyInput(p));

    t = new Timer(10, this);
    t.start();
}

Feel free to ask for more code samples if you need to!


回答1:


The hacky solution is to call requestFocusInWindow() on the JPanel to make sure it has focus for KeyListener/KeyAdapter this should only be called after the Componnet has been added (though to be sure my component has focus I called it after the JFrame is refreshed via revalidate() and repaint()) for example:

public class MyUI {

    //will switch to the gamepanel by removing all components from the frame and adding GamePanel
    public void switchToGamePanel() {
        frame.getContentPane().removeAll();

        GamePanel gp = new GamePanel();//keylistener/keyadapter was added to Jpanel here

        frame.add(gp);//add component. we could call requestFocusInWindow() after this but to be 98%  sure it works lets call after refreshing JFrame

        //refresh JFrame
        frame.pack();
        frame.revalidate();
        frame.repaint();

        gp.requestFocusInWindow();
    }

}
class GamePanel extends JPanel { 

      public GamePanel() {
          //initiate Jpanel and Keylistener/adapter
      }

}

However you should use Swing KeyBindings (+1 to @Reimeus comment).

Have a read here to get familiar with them:

  • How to Use Key Bindings

Now that you have read that lets show another example to help clarify (though Oracle did a good job)

If we wanted to add a KeyBinding to a certain JComponent i.e JButton for Esc you would do:

void addKeyBinding(JComponent jc) {
        jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "esc pressed");
        jc.getActionMap().put("esc pressed", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                System.out.println("Esc pressed");
            }
        });

        jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true), "esc released");
        jc.getActionMap().put("esc released", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                System.out.println("Esc released");
            }
        });
}

the above method would be called like:

JButton b=..;//create an instance of component which is swing

addKeyBinding(b);//add keybinding to the component

Please note:

1) You would not need both KeyBindings, I just showed how to get different key state and act appropriately using Keybindings.

2) This method will add a Keybinding which will be activated as long as Esc is pressed and the component is in the window which has focus, you can change this by specifying another InputMap i.e:

jc.getInputMap(JComponent.WHEN_FOCUSED).put(..);//will only activated when component has focus


来源:https://stackoverflow.com/questions/14004263/java-keylistener-not-responding-after-switching-jpanels

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!