java keylistener 未调用
Posted
技术标签:
【中文标题】java keylistener 未调用【英文标题】:java keylistener not called 【发布时间】:2012-01-18 21:59:35 【问题描述】:我在 Java 中使用 KeyListener
编写了一个示例代码,
我创建了一个 JPanel
,然后将其可聚焦设置为 true,我创建了一个 KeyListener,请求焦点,然后将 KeyListener 添加到我的面板中。但是永远不会调用 keyListener 的方法。似乎虽然我请求了焦点,但它没有焦点。
有人可以帮忙吗?
listener = new KeyLis();
this.setFocusable(true);
this.requestFocus();
this.addKeyListener(listener);
class KeyLis implements KeyListener
@Override
public void keyPressed(KeyEvent e)
currentver += 5;
switch (e.getKeyCode())
case KeyEvent.VK_LEFT : if(horizontalyInBounds()) currentPos-= 5;
break;
case KeyEvent.VK_RIGHT: if(horizontalyInBounds()) currentPos+= 5;
break;
repaint();
@Override
public void keyReleased(KeyEvent e)
// TODO Auto-generated method stub
@Override
public void keyTyped(KeyEvent e)
如果需要任何可运行的代码:
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class test extends JFrame
private AreaOfGame areaOfGame;
public test()
super("");
setVisible(true);
this.setBackground(Color.darkGray);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
setLayout(null);
setBounds(200, 10, 400, 700);
areaOfGame = new AreaOfGame();
this.add(areaOfGame);
startGame();
public int generateNext()
Random r = new Random();
int n = r.nextInt(7);
return n;
public void startGame()
while(!areaOfGame.GameOver())
areaOfGame.startGame(generateNext());
public static void main(String[] args)
new MainFrame();
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JPanel;
public class AreaOfGame extends JPanel
private static final int rightside = 370;
private int bottom;
private int top;
private int currentPos;
private int currentver;
private KeyLis listener;
public AreaOfGame()
super();
bottom = 650;
top = 50;
setLayout(null);
setBounds(20, 50, 350, 600);
setVisible(true);
this.setBackground(Color.lightGray);
listener = new KeyLis();
this.setFocusable(true);
if(this.requestFocus(true))
System.out.println("true");;
this.addKeyListener(listener);
currentPos = 150;
currentver=0;
public void startGame(int n)
while(verticallyInBound())
System.out.println("anything");
public boolean verticallyInBound()
if(currentPos<= bottom -50)
return true;
return false;
public boolean GameOver()
if(top>= bottom)
System.out.println("game over");
return true;
else return false;
public boolean horizontalyInBounds()
if(currentPos<=rightside && currentPos>= 20)
return true;
else return false;
class KeyLis implements KeyListener
@Override
public void keyPressed(KeyEvent e)
System.out.println("called");
currentver += 5;
switch (e.getKeyCode())
case KeyEvent.VK_LEFT : if(horizontalyInBounds()) currentPos-= 5; break;
case KeyEvent.VK_RIGHT: if(horizontalyInBounds()) currentPos+= 5; break;
repaint();
@Override
public void keyReleased(KeyEvent e)
// TODO Auto-generated method stub
@Override
public void keyTyped(KeyEvent e)
System.out.println("called 3");
【问题讨论】:
如果你能给我们你的“KeyLis”课程会有所帮助,也许问题就在那里。 谢谢,我添加了监听类 嗯...我想我曾经遇到过类似的问题。尝试在 keyPressed(KeyEvent e) 方法的末尾调用方法“e.consume()”。让我知道它是否有效。 @BBB 尝试将System.out.println("something unique")
添加到侦听器的每个方法中。这将确保它们实际上没有被调用。
您的while (true)
循环正在锁定您的事件线程。
【参考方案1】:
我敢打赌,您会在 JPanel 被渲染之前请求焦点(在***窗口调用 pack()
或 setVisible(true)
之前),如果是这样,这将不起作用。只有在渲染组件之后 才可能授予焦点请求。您是否检查过您对requestFocus()
的呼叫已返回?它必须返回 true 才能使您的呼叫有任何成功的机会。另外最好使用requestFocusInWindow()
而不是requestFocus()
。
但更重要的是,您不应该为此使用 KeyListeners,而是使用键绑定,这是 Swing 本身用来响应按键的更高级别的概念。
编辑SSCCE 的示例:
import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;
public class TestKeyListener extends JPanel
private KeyLis listener;
public TestKeyListener()
add(new JButton("Foo")); // something to draw off focus
listener = new KeyLis();
this.setFocusable(true);
this.requestFocus();
this.addKeyListener(listener);
@Override
public Dimension getPreferredSize()
return new Dimension(300, 200);
private class KeyLis extends KeyAdapter
@Override
public void keyPressed(KeyEvent e)
switch (e.getKeyCode())
case KeyEvent.VK_LEFT:
System.out.println("VK_LEFT pressed");
break;
case KeyEvent.VK_RIGHT:
System.out.println("VK_RIGHT pressed");
break;
private static void createAndShowGui()
TestKeyListener mainPanel = new TestKeyListener();
JFrame frame = new JFrame("TestKeyListener");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
public static void main(String[] args)
SwingUtilities.invokeLater(new Runnable()
public void run()
createAndShowGui();
);
编辑 2 以及使用键绑定的等效SSCCE:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class TestKeyBindings extends JPanel
public TestKeyBindings()
add(new JButton("Foo")); // something to draw off focus
setKeyBindings();
private void setKeyBindings()
ActionMap actionMap = getActionMap();
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition );
String vkLeft = "VK_LEFT";
String vkRight = "VK_RIGHT";
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), vkLeft);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), vkRight);
actionMap.put(vkLeft, new KeyAction(vkLeft));
actionMap.put(vkRight, new KeyAction(vkRight));
@Override
public Dimension getPreferredSize()
return new Dimension(300, 200);
private class KeyAction extends AbstractAction
public KeyAction(String actionCommand)
putValue(ACTION_COMMAND_KEY, actionCommand);
@Override
public void actionPerformed(ActionEvent actionEvt)
System.out.println(actionEvt.getActionCommand() + " pressed");
private static void createAndShowGui()
TestKeyBindings mainPanel = new TestKeyBindings();
JFrame frame = new JFrame("TestKeyListener");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
public static void main(String[] args)
SwingUtilities.invokeLater(new Runnable()
public void run()
createAndShowGui();
);
编辑 3
关于您最近的 SSCCE,您的 while (true)
循环正在阻塞您的 Swing 事件线程,并且可能会阻止用户交互或绘画的发生。最好使用 Swing Timer 而不是 while (true)
。例如:
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class BbbTest extends JFrame
private AreaOfGame areaOfGame;
public BbbTest()
super("");
// setVisible(true);
this.setBackground(Color.darkGray);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
setLayout(null);
setBounds(200, 10, 400, 700);
areaOfGame = new AreaOfGame();
this.add(areaOfGame);
setVisible(true);
startGame();
public int generateNext()
Random r = new Random();
int n = r.nextInt(7);
return n;
public void startGame()
// while (!areaOfGame.GameOver())
// areaOfGame.startGame(generateNext());
//
areaOfGame.startGame(generateNext());
public static void main(String[] args)
new BbbTest();
class AreaOfGame extends JPanel
private static final int rightside = 370;
private int bottom;
private int top;
private int currentPos;
private int currentver;
private KeyLis listener;
public AreaOfGame()
super();
bottom = 650;
top = 50;
setLayout(null);
setBounds(20, 50, 350, 600);
setVisible(true);
this.setBackground(Color.lightGray);
listener = new KeyLis();
this.setFocusable(true);
if (this.requestFocus(true))
System.out.println("true");
;
this.addKeyListener(listener);
currentPos = 150;
currentver = 0;
public void startGame(int n)
// while (verticallyInBound())
// System.out.println("anything");
//
int timeDelay = 50; // msecs delay
new Timer(timeDelay , new ActionListener()
public void actionPerformed(ActionEvent arg0)
System.out.println("anything");
).start();
public boolean verticallyInBound()
if (currentPos <= bottom - 50)
return true;
return false;
public boolean GameOver()
if (top >= bottom)
System.out.println("game over");
return true;
else
return false;
public boolean horizontalyInBounds()
if (currentPos <= rightside && currentPos >= 20)
return true;
else
return false;
class KeyLis implements KeyListener
@Override
public void keyPressed(KeyEvent e)
System.out.println("called");
currentver += 5;
switch (e.getKeyCode())
case KeyEvent.VK_LEFT:
if (horizontalyInBounds())
currentPos -= 5;
break;
case KeyEvent.VK_RIGHT:
if (horizontalyInBounds())
currentPos += 5;
break;
repaint();
@Override
public void keyReleased(KeyEvent e)
// TODO Auto-generated method stub
@Override
public void keyTyped(KeyEvent e)
System.out.println("called 3");
【讨论】:
实际上这些都是在我的框架有 pack() 和 setVisible(true) 之后完成的。如果使用键绑定是唯一的选择,我会这样做,但我真的很想知道为什么会这样不工作,因为之前似乎没有任何机构有这个问题,我检查了空指针、焦点、被调用的方法、正在添加的侦听器,但没有工作。 @BBB:再次,您是否检查过您的requestFocus()
方法调用已返回?是返回真还是假?
一直返回false
这实际上是我在我的问题中提到的,虽然我要求,但它似乎没有重点,这意味着它返回false,我不知道如何让它返回true。
@BBB:我的观点完全正确。那么除非你改变一些东西,否则你就没有成功的希望。如果您可以创建并发布一个小的可编译和可运行的程序,我们可以运行它并演示您的问题,这样我们就可以自己看到它,sscce。【参考方案2】:
可以使用“TAB”按钮在按钮和按键监听器之间切换。 我有一个带有一个按钮的程序,按下它后,按键监听器不起作用。 我意识到,如果你按下“TAB”按钮,程序的“注意”或“焦点”就会返回到关键监听器。
也许这会有所帮助:http://docstore.mik.ua/orelly/java-ent/jfc/ch03_08.htm
【讨论】:
以上是关于java keylistener 未调用的主要内容,如果未能解决你的问题,请参考以下文章