11

当使用我的 JPanel 类中的 KeyListener 按下箭头键之一时,我正在尝试做某事。这是我的代码:

public class TestPanel extends JPanel implements KeyListener{

    public TestPanel(){
        this.addKeyListener(this);
        this.setFocusable(true);
        this.requestFocusInWindow();
    }

    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            System.out.println("Right");

        }

        if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            System.out.println("Left");
        }

    }

    public void keyTyped(KeyEvent e) {}
    public void keyReleased(KeyEvent e) {}
}

我的主要方法将此面板的新实例添加到框架并显示它。我需要将 keylistener 添加到 JFrame 吗?在我的情况下,这将是困难且低效的,所以如果可能的话,我想让它与这个 JPanel 一起工作。有人知道我在做什么错吗?

编辑:键绑定代码也不起作用:

public class GamePanel extends JPanel implements ActionListener{

//Constructor
public GamePanel(){

    setupKeyBinding();
    this.setFocusable(true);
    this.requestFocusInWindow();


}

private void setupKeyBinding() {
    int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
    InputMap inMap = getInputMap(condition);
    ActionMap actMap = getActionMap();

    inMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "Left");
    actMap.put("Left", new leftAction());
}

private class leftAction extends AbstractAction {

       public void actionPerformed(ActionEvent e) {
          System.out.println("test");
       }
}

public void actionPerformed(ActionEvent e) {
    //some other game info
}
} 

有人能告诉我为什么这也不起作用吗?(我的第二个动作监听器用于我的游戏所需的其他东西)

4

4 回答 4

11

如果你搜索这个问题,你会看到它被问过并且已经被解决了很多次。

  • KeyListeners 需要在焦点组件上才能工作。一种解决方案是在第一次使其可聚焦之后为您的组件提供焦点。
  • 然而,从长远来看,更好的是使用键绑定。谷歌这个教程。

请查看我对这个问题的回答以了解更多信息,包括许多血淋淋的细节。

于 2013-05-13T21:15:28.817 回答
7

作为参考,我使用您的方法创建了一个示例;虽然它有效,但它也暗示了代码中其他地方的焦点问题。键绑定避免了这种情况,如此处所示。

附录:这是我的工作键绑定。

private static class TestPanel extends JPanel {

    private static final String LEFT = "Left";
    private Action left = new AbstractAction(LEFT) {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println(LEFT);
        }
    };
    private static final String RIGHT = "Right";
    private Action right = new AbstractAction(RIGHT) {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println(RIGHT);
        }
    };

    public TestPanel() {
        this.getInputMap().put(
            KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), LEFT);
        this.getActionMap().put(LEFT, left);
        this.getInputMap().put(
            KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), RIGHT);
        this.getActionMap().put(RIGHT, right);
    }
}

原 SSCCE:

import java.awt.EventQueue;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * @see https://stackoverflow.com/a/16531380/230513
 */
public class Test {

    private void display() {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new TestPanel());
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static class TestPanel extends JPanel implements KeyListener {

        public TestPanel() {

            this.addKeyListener(this);
            this.setFocusable(true);
            this.requestFocusInWindow();
        }

        @Override
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
                System.out.println("Right");
            }

            if (e.getKeyCode() == KeyEvent.VK_LEFT) {
                System.out.println("Left");
            }
        }

        @Override
        public void keyTyped(KeyEvent e) {
        }

        @Override
        public void keyReleased(KeyEvent e) {
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Test().display();
            }
        });
    }
}
于 2013-05-13T21:23:34.177 回答
1

对于接收关键事件,JPanel您必须设置焦点:

setFocusable(true);
requestFocus(); 

现在有JPanel焦点,所以它接收关键事件

于 2019-05-21T11:09:36.263 回答
0

我必须做两件事:我添加了 comp.setFocusable(true); 到监听关键事件的组件 comp,我添加了 comp.requestFocus(); 到导致comp失去焦点的每个动作。

于 2015-06-16T17:30:29.023 回答