【发布时间】:2018-05-30 06:59:44
【问题描述】:
我正在尝试从 Java KeyListeners 转移到 KeyBindings 来制作动画,但它们会工作几秒钟然后完全停止。当动作触发时,我将消息打印到控制台,并且这些消息停止,所以不仅仅是绘画不起作用,而是按键被按下时触发的动作。
我的类扩展了 JFrame,我只是向它添加了一个 JPanel,并在 JPanel 中添加了一个 JLabel。我使用由 Actions 切换的标志来指示 JLabel 应该如何移动,并且我使用 JFrame 的 actionPerformed 方法来检查标志的状态并调整 JLabel 的位置。
我尝试在getInputMap 方法中添加JComponent.WHEN_IN_FOCUSED_WINDOW,但没有任何区别。
代码如下:
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
public class KeyBindingTest extends JFrame implements ActionListener {
long counter = 0;
int speed = 5;
boolean isUp = false, isDown = false, isLeft = false, isRight = false;
JLabel j = new JLabel();
JPanel p = new JPanel();
Timer t;
Action upPressed = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("up on");
isUp = true;
}
};
Action upReleased = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
isUp = false;
System.out.println("up off");
}
};
Action downPressed = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("down on");
isDown = true;
}
};
Action downReleased = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("down off");
isDown = false;
}
};
Action leftPressed = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("left on");
isLeft = true;
}
};
Action leftReleased = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("left off");
isLeft = false;
}
};
Action rightPressed = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("right on");
isRight = true;
}
};
Action rightReleased = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("right off");
isRight = false;
}
};
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
// The try/catch block prevents errors from crashing the program
try {
KeyBindingTest window = new KeyBindingTest(); // Create and setup the main game window
window.run(); // show the new window
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void run() {
this.setBounds(640, 400, 640, 400);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p.setBounds(0, 0, this.getWidth(), this.getHeight());
p.setVisible(true);
p.setBackground(Color.blue);
p.setOpaque(true);
p.setFocusable(true);
p.setLayout(null);
j.setBounds(320, 200, 10, 10);
j.setVisible(true);
j.setBackground(Color.red);
j.setOpaque(true);
this.add(p);
p.add(j);
p.requestFocusInWindow();
setupKeyBindings();
t = new Timer(1000 / 40, this);
t.start();
}
private void setupKeyBindings() {
p.getInputMap().put(KeyStroke.getKeyStroke("W"), "moveUp");
p.getActionMap().put("moveUp", upPressed);
p.getInputMap().put(KeyStroke.getKeyStroke("released W"), "stopUp");
p.getActionMap().put("stopUp", upReleased);
p.getInputMap().put(KeyStroke.getKeyStroke("S"), "moveDown");
p.getActionMap().put("moveDown", downPressed);
p.getInputMap().put(KeyStroke.getKeyStroke("released S"), "stopDown");
p.getActionMap().put("stopDown", downReleased);
p.getInputMap().put(KeyStroke.getKeyStroke("A"), "moveLeft");
p.getActionMap().put("moveLeft", leftPressed);
p.getInputMap().put(KeyStroke.getKeyStroke("released A"), "stopLeft");
p.getActionMap().put("stopLeft", leftReleased);
p.getInputMap().put(KeyStroke.getKeyStroke("D"), "moveRight");
p.getActionMap().put("moveRight", rightPressed);
p.getInputMap().put(KeyStroke.getKeyStroke("released D"), "stopRight");
p.getActionMap().put("stopRight", rightReleased);
}
@Override
public void actionPerformed(ActionEvent e) {
counter++;
System.out.println(counter);
if (isUp) {
j.setLocation(j.getX(), j.getY() - speed);
}
if (isDown) {
j.setLocation(j.getX(), j.getY() + speed);
}
if (isLeft) {
j.setLocation(j.getX() - speed, j.getY());
}
if (isRight) {
j.setLocation(j.getX() + speed, j.getY());
}
repaint();
}
}
【问题讨论】:
-
好吧,经过大量测试,我不知道。我尝试了多种组合,但仍然可以得到相同的结果。有时绑定会在短时间内停止响应并重新启动,有时它们会完全停止。我使用了
KeyboardFocusManager.addKeyEventDispatcher并且可以验证按键仍然由 EDT 注册/处理,但由于某种原因它们没有被传递到组件 - 我闻到了一个错误,但我不能确定 -
感谢您的努力,我很高兴听到我没有失去理智!
-
我之前尝试过其他几个例子,都可以,主要区别是他们使用了自定义的绘画路线
-
我这样做是从 KeyListeners/JComponents 迁移到 KeyBindings/JComponents 的一部分,所以我不妨将整个迁移到 KeyBindings/Painting,所以我会尝试一下。谢谢!
标签: java swing key-bindings