【问题标题】:Java KeyListener not responding after switching JPanels切换 JPanel 后 Java KeyListener 没有响应
【发布时间】:2012-12-09 20:49:09
【问题描述】:

当我在 JPanel 之间切换时,我遇到了 KeyListener 没有响应(由于没有获得焦点)的问题。

我在 Google 上搜索过这个并且知道要解决这个问题我需要使用 KeyBindings,但我不喜欢 KeyBindings。所以我想知道,还有其他方法吗?

这是具有无响应 KeyListener 的 JPanel 的初始化代码:

    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();
}

如果需要,请随时索取更多代码示例!

【问题讨论】:

  • ...但我不喜欢 KeyBindings:使用它们有什么问题?
  • 它们有点乱(我的口味)......关于如何使用它们的所有教程都过于复杂了。
  • -1 知道推荐的方法并坚持不使用它 - 耸耸肩,这是你在浪费时间......

标签: java swing timer jpanel keylistener


【解决方案1】:

hacky 的解决方案是在 JPanel 上调用 requestFocusInWindow() 以确保它具有 KeyListener/KeyAdapter 的焦点,这应该只在添加 Componnet 之后调用(尽管要确保我的组件具有焦点我在通过revalidate()repaint() 刷新JFrame 之后调用它)例如:

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
      }

}

但是你应该使用 Swing KeyBindings(+1 到 @Reimeus 评论)。

阅读此处以熟悉它们:

现在您已经阅读了,让我们展示另一个示例来帮助澄清(尽管 Oracle 做得很好)

如果我们想将KeyBinding 添加到某个JComponentJButton for Esc 你可以这样做:

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");
            }
        });
}

上面的方法会这样调用:

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

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

请注意:

1) 你不需要两个KeyBindings,我只是展示了如何使用Keybindings 获得不同的关键状态并采取适当的行动。

2) 此方法将添加一个Keybinding,只要按下 Esc 并且组件位于具有焦点的窗口中,就会激活该 Keybinding,您可以通过指定另一个 @987654339 来更改它@即:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    • 1970-01-01
    • 2012-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多