Keylistener 不适用于 JPanel
Posted
技术标签:
【中文标题】Keylistener 不适用于 JPanel【英文标题】:Keylistener not working for JPanel 【发布时间】:2013-05-08 00:02:40 【问题描述】:当使用我的 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)
我的 main 方法将此面板的新实例添加到框架并显示它。我需要将 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
谁能告诉我为什么这也不起作用? (我的第二个动作监听器用于我的游戏所需的其他东西)
【问题讨论】:
另一个想法可能是创建一个内部类并使用类似:“this.addKeyListener(inner class/anonymous inner class);” java keylistener not called的可能重复 【参考方案1】:如果你搜索这个问题,你会看到它被问过并且已经被解决了很多次。
KeyListeners 需要在焦点组件上才能工作。一种解决方案是先使您的组件具有焦点,然后再使其成为焦点。 不过,最好还是使用键绑定。谷歌这方面的教程。请查看我对this question 的回复以了解更多信息,包括许多血淋淋的细节。
【讨论】:
谢谢,我会研究键绑定,但是对于这个问题,我已经查看了各种解决方案,但看不出我在做什么不同。如何让我的组件获得焦点?我想我是通过使用 requestFocusInWindow() 焦点行为因平台而异;此外,如果有任何其他可聚焦的组件,KeyListener
在这方面将是脆弱的。
@user2373733 键绑定是要走的路。只需放下您的 KeyListener:它将为您节省一些时间并避免将来出现错误。
所以我阅读了 oracle 文档并查看了您的示例并尝试使用键绑定,但它没有工作,所以我去复制了您的键绑定代码并尝试了它,它仍然不起作用。目前不知道该怎么做
@user2373733:您必须创建并发布sscce。如果我们要帮助您解决此错误,您或我们必须隔离并识别错误,如果没有 sscce,我们很难做到这一点。【参考方案2】:
作为参考,我使用您的方法创建了一个示例;虽然它有效,但它也暗示了代码中其他地方的焦点问题。 Key Bindings 避免这种情况,如图here。
附录:这是我的工作键绑定。
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://***.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();
);
【讨论】:
啊,谢谢,我不知道什么会引起关注。我在测试时将添加到框架中的所有其他面板设置为不可聚焦,以确保没有任何干扰。我现在正在尝试键绑定,虽然我对很多这些东西都不熟悉 我已将该代码添加到我的帖子中,如果有人能告诉我为什么这也不起作用,我将不胜感激! 我在上面添加了一个工作示例;如果您发布新问题,请告诉我们。 谢谢,在此之前我会做更多的研究。我问过我的老师关于我的问题以及其他很多人,但没有人能弄清楚。基本上它只有在我的面板有焦点时才有效。我认为这只适用于关键听众 缺少更多上下文,很难说;您尝试了三个输入映射中的每一个吗?【参考方案3】:要在JPanel
上接收关键事件,您必须设置焦点:
setFocusable(true);
requestFocus();
JPanel
现在有了焦点,所以它接收关键事件
【讨论】:
【参考方案4】:我必须做两件事:我添加了 comp.setFocusable(true);到监听关键事件的组件 comp,我添加了 comp.requestFocus();到导致 comp 失去焦点的每个动作。
【讨论】:
这在最好的情况下是一种黑客攻击,并且在窗口失去焦点或另一个窃取焦点的组件时很容易被破坏 - 正确的答案是使用键绑定 API以上是关于Keylistener 不适用于 JPanel的主要内容,如果未能解决你的问题,请参考以下文章
用于 Enter 键的 Java 可编辑 JCombobox Keylistener 事件
Android 的 EditText 问题:KeyListener