Java Keylistener 不适用于 JPanel

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16530775/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 07:21:01  来源:igfitidea点击:

Keylistener not working for JPanel

javaswingkeylistener

提问by user2373733

I am trying to do something when one of the arrow keys are pressed using the KeyListener in my JPanel class. Here is my code:

当使用 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) {}
}

My main method adds a new instance of this panel to a frame and displays it. Do I need to add the keylistener to the JFrame? In my case, this would be difficult and inefficient, so I would like to make it work with this JPanel if possible. Anyone know what I am doing wrong?

我的 main 方法将这个面板的一个新实例添加到一个框架中并显示它。我需要将密钥侦听器添加到 JFrame 吗?在我的情况下,这会很困难且效率低下,所以如果可能的话,我想让它与这个 JPanel 一起工作。有谁知道我做错了什么?

EDIT: Key Bindings code that does not work either:

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

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
}
} 

Can someone tell me why this doesnt work either? (my second action listener is for other stuff needed for my game)

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

采纳答案by Hovercraft Full Of Eels

If you search this problem, you'll see that it is asked and has been solved many times.

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

  • KeyListeners need to be on the focused component to work. One solution is to give your component the focus after first making it focusable.
  • Better by a long shot however is to use Key Bindings. Google the tutorial on this.
  • KeyListeners 需要在焦点组件上才能工作。一种解决方案是在首先使组件可聚焦后为其赋予焦点。
  • 然而,更好的是使用键绑定。谷歌这个教程。

Please have a look at my answer to this questionfor more on this, including many of the gory details.

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

回答by trashgod

For reference, I've create an example using your approach; while it works, it also suggests a focus problem elsewhere in your code. Key Bindingsavoid this, as shown here.

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

Addendum: Here's my working key binding.

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

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

Original SSCCE:

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

回答by Donald Smith

I had to do two things: I added comp.setFocusable(true); to the component comp that listens to key events, and I added comp.requestFocus(); to each action which caused comp to lose the focus.

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

回答by Dmitriy Potapov

For receives key events on JPanelyou must set focus:

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

setFocusable(true);
requestFocus(); 

the JPanelnow has focus, so it receives key events

JPanel现在有重点,所以它发出的按键事件