KeyListener 不工作的问题
issue with KeyListener not working
虽然我已经编码了很长一段时间,但我似乎无法解决我遇到的这个问题(我几乎可以肯定这是我无法捕捉到的小语法错误,而不是逻辑错误)。我正在制作音板,并使用键盘上的数字键盘。我有一个 KeyManager class:
public class KeyManager implements KeyListener{
private boolean[] keys;
private boolean nine, eight, seven, six, five, four, three, two, one;
public KeyManager(){
keys = new boolean [256];
}
public void update(){
nine = keys[KeyEvent.VK_9];
eight = keys[KeyEvent.VK_8];
seven = keys[KeyEvent.VK_7];
six = keys[KeyEvent.VK_6];
five = keys[KeyEvent.VK_5];
four = keys[KeyEvent.VK_4];
three = keys[KeyEvent.VK_3];
two = keys[KeyEvent.VK_2];
one = keys[KeyEvent.VK_1];
}
public void keyPressed(KeyEvent e) {
keys[e.getKeyCode()] = true;
}
public void keyReleased(KeyEvent e) {
keys[e.getKeyCode()] = false;
}
public void keyTyped(KeyEvent e) {
}
public boolean isNine() {
return nine;
}
public boolean isEight() {
return eight;
}
public boolean isSeven() {
return seven;
}
public boolean isSix() {
return six;
}
public boolean isFive() {
return five;
}
public boolean isFour() {
return four;
}
public boolean isThree() {
return three;
}
public boolean isTwo() {
return two;
}
public boolean isOne() {
return one;
}
}
这很简单,我正在使用扩展 JFrame 作为主要 UI 显示的框架 class:
public class Frame extends JFrame implements Runnable{
private static final long serialVersionUID = 1L;
private Pane pane;
private ArrayList<Circle> c;
private KeyManager keyManager;
public Frame(){
keyManager = new KeyManager();
this.addKeyListener(keyManager);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.getContentPane().setPreferredSize(new Dimension(400, 400));
this.pack();
this.setLocationRelativeTo(null);
pane = new Pane();
this.add(pane);
c = new ArrayList<Circle>();
c.add(new Circle(20, 140));
c.add(new Circle(80, 140));
c.add(new Circle(140, 140));
c.add(new Circle(20, 80));
c.add(new Circle(80, 80));
c.add(new Circle(140, 80));
c.add(new Circle(20, 20));
c.add(new Circle(80, 20));
c.add(new Circle(140, 20));
this.setVisible(true);
}
public void init(){
pane.draw(c);
}
public void update(){
pane.draw(c);
keyManager.update();
if(keyManager.isNine()){
System.out.println("pressed");
c.get(8).press();
}
else{
c.get(8).release();
System.out.println("unpressed");
}
}
public void run() {
init();
int fps = 60;
double timePerUpdate = 1000000000/fps;
double delta = 0;
long now;
long lastTime= System.nanoTime();
long timer = 0;
int updates = 0;
while(true){
now = System.nanoTime();
delta += (now - lastTime) / timePerUpdate;
timer+= now - lastTime;
lastTime = now;
if(delta >= 1){
update();
updates ++;
delta--;
}
if(timer >= 1000000000){
//System.out.println("Updates and Frames: "+ updates);
updates = 0;
timer = 0;
}
}
}
}
出于某种原因,当我按下键盘上的 "nine" 时,它不会打印出 Frame.update() 方法中的按下,而只会打印出 "unpressed." I不知道是什么导致了这个问题。这是我第一次使用 KeyManager class 而不是让 Frame 完成所有提升工作,因为这是一个很好的编程习惯,但从逻辑上讲它应该可以工作,除非我遗漏了什么...
您似乎根本没有注册您的密钥管理器。
JFrame 如何知道它有一个关键侦听器?
在框架的最顶部添加这行代码 class this.addKeyListener(new KeyManager());
像这样:
public Frame(){
this.addKeyListener(new KeyManager()); // New code
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.getContentPane().setPreferredSize(new Dimension(400, 400));
编辑:为了将来参考,请始终检查 javadoc,因为在这种情况下,答案就在您身边:
The listener object created from that class is then registered with a
component using the component's addKeyListener method.
Java文档:
https://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyListener.html
官方教程中再次提到addKeyListener
:
https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
编辑评论:
让我们通过向您的按键事件添加一些代码来调试问题。通过这样做,我们可以找到几件事。
1) 是否触发了关键事件。
2) 按下的键码和字符是什么
public void keyPressed(KeyEvent e) {
System.out.println("The following key was pressed: "+e.getKeyChar());
System.out.println("With the following key code: "+e.getKeyCode());
System.out.println("Is that the expected output?");
keys[e.getKeyCode()] = true;
}
你从我们的新调试代码中得到了正确的输出吗?键码是否正确,字符是否正确?你的其他数字键能用吗?
这里要记住的一件事是,数字键盘上的数字与普通数字键的键码不同。我强烈建议您重新编写代码以使用 e.getKeyChar()
或在 update()
方法中包含数字键盘代码,并在按下普通键盘或数字键盘键时使用 IF 语句并将布尔值设置为 true/false.
虽然我已经编码了很长一段时间,但我似乎无法解决我遇到的这个问题(我几乎可以肯定这是我无法捕捉到的小语法错误,而不是逻辑错误)。我正在制作音板,并使用键盘上的数字键盘。我有一个 KeyManager class:
public class KeyManager implements KeyListener{
private boolean[] keys;
private boolean nine, eight, seven, six, five, four, three, two, one;
public KeyManager(){
keys = new boolean [256];
}
public void update(){
nine = keys[KeyEvent.VK_9];
eight = keys[KeyEvent.VK_8];
seven = keys[KeyEvent.VK_7];
six = keys[KeyEvent.VK_6];
five = keys[KeyEvent.VK_5];
four = keys[KeyEvent.VK_4];
three = keys[KeyEvent.VK_3];
two = keys[KeyEvent.VK_2];
one = keys[KeyEvent.VK_1];
}
public void keyPressed(KeyEvent e) {
keys[e.getKeyCode()] = true;
}
public void keyReleased(KeyEvent e) {
keys[e.getKeyCode()] = false;
}
public void keyTyped(KeyEvent e) {
}
public boolean isNine() {
return nine;
}
public boolean isEight() {
return eight;
}
public boolean isSeven() {
return seven;
}
public boolean isSix() {
return six;
}
public boolean isFive() {
return five;
}
public boolean isFour() {
return four;
}
public boolean isThree() {
return three;
}
public boolean isTwo() {
return two;
}
public boolean isOne() {
return one;
}
}
这很简单,我正在使用扩展 JFrame 作为主要 UI 显示的框架 class:
public class Frame extends JFrame implements Runnable{
private static final long serialVersionUID = 1L;
private Pane pane;
private ArrayList<Circle> c;
private KeyManager keyManager;
public Frame(){
keyManager = new KeyManager();
this.addKeyListener(keyManager);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.getContentPane().setPreferredSize(new Dimension(400, 400));
this.pack();
this.setLocationRelativeTo(null);
pane = new Pane();
this.add(pane);
c = new ArrayList<Circle>();
c.add(new Circle(20, 140));
c.add(new Circle(80, 140));
c.add(new Circle(140, 140));
c.add(new Circle(20, 80));
c.add(new Circle(80, 80));
c.add(new Circle(140, 80));
c.add(new Circle(20, 20));
c.add(new Circle(80, 20));
c.add(new Circle(140, 20));
this.setVisible(true);
}
public void init(){
pane.draw(c);
}
public void update(){
pane.draw(c);
keyManager.update();
if(keyManager.isNine()){
System.out.println("pressed");
c.get(8).press();
}
else{
c.get(8).release();
System.out.println("unpressed");
}
}
public void run() {
init();
int fps = 60;
double timePerUpdate = 1000000000/fps;
double delta = 0;
long now;
long lastTime= System.nanoTime();
long timer = 0;
int updates = 0;
while(true){
now = System.nanoTime();
delta += (now - lastTime) / timePerUpdate;
timer+= now - lastTime;
lastTime = now;
if(delta >= 1){
update();
updates ++;
delta--;
}
if(timer >= 1000000000){
//System.out.println("Updates and Frames: "+ updates);
updates = 0;
timer = 0;
}
}
}
}
出于某种原因,当我按下键盘上的 "nine" 时,它不会打印出 Frame.update() 方法中的按下,而只会打印出 "unpressed." I不知道是什么导致了这个问题。这是我第一次使用 KeyManager class 而不是让 Frame 完成所有提升工作,因为这是一个很好的编程习惯,但从逻辑上讲它应该可以工作,除非我遗漏了什么...
您似乎根本没有注册您的密钥管理器。 JFrame 如何知道它有一个关键侦听器?
在框架的最顶部添加这行代码 class this.addKeyListener(new KeyManager());
像这样:
public Frame(){
this.addKeyListener(new KeyManager()); // New code
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.getContentPane().setPreferredSize(new Dimension(400, 400));
编辑:为了将来参考,请始终检查 javadoc,因为在这种情况下,答案就在您身边:
The listener object created from that class is then registered with a component using the component's addKeyListener method.
Java文档: https://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyListener.html
官方教程中再次提到addKeyListener
:
https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
编辑评论:
让我们通过向您的按键事件添加一些代码来调试问题。通过这样做,我们可以找到几件事。
1) 是否触发了关键事件。
2) 按下的键码和字符是什么
public void keyPressed(KeyEvent e) {
System.out.println("The following key was pressed: "+e.getKeyChar());
System.out.println("With the following key code: "+e.getKeyCode());
System.out.println("Is that the expected output?");
keys[e.getKeyCode()] = true;
}
你从我们的新调试代码中得到了正确的输出吗?键码是否正确,字符是否正确?你的其他数字键能用吗?
这里要记住的一件事是,数字键盘上的数字与普通数字键的键码不同。我强烈建议您重新编写代码以使用 e.getKeyChar()
或在 update()
方法中包含数字键盘代码,并在按下普通键盘或数字键盘键时使用 IF 语句并将布尔值设置为 true/false.