我正在尝试使用Java Swing做一些小游戏,并且已经走了很远,但是现在我的KeyListener没有使用keyPressed方法。
这是我的一些代码
public class Screen extends JPanel implements Runnable{
private static final int WIDTH = 300, HEIGHT = 300, RIGHT = 0, LEFT = 1, UP = 2, DOWN = 3, STILL = 4;
private Thread thread;
private boolean running = false;
private int direction = DOWN;
public Screen() {
setFocusable(true);
addKeyListener(new Key());
setPreferredSize(new Dimension(WIDTH, HEIGHT));
start();
}
public void tick(){
System.out.println(direction)
}
public void start() {
running = true;
thread = new Thread(this, "Game Loop");
thread.start();
}
public void run() {
while (running) {
tick();
repaint();
}
}
private class Key implements KeyListener{
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_D) {
direction = RIGHT;
}
if (key == KeyEvent.VK_A) {
direction = LEFT;
}
if (key == KeyEvent.VK_W) {
direction = UP;
}
if (key == KeyEvent.VK_S) {
direction = DOWN;
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
}
我正在查看控制台,并且希望无论我按什么按钮,输出都将从3(即DOWN)改变,但是从没有改变。一段时间后,我意识到keyPressed方法出了点问题,我只是不知道是什么。
您不需要单独的“游戏循环”线程。 Swing是事件驱动的。当用户按下计算机键盘上的键时,将调用您的键侦听器代码。
如[[MadProgrammer在他的comment to your question中提到的
从EDT上下文之外修改UI状态可能会导致绘画问题
换句话说,
Swing
是single threaded,并且该线程称为Event Dispatch Thread(EDT),并且所有更改GUI的代码都应仅在EDT上执行。” >下面的代码是一个独立的Swing
应用程序,它显示可聚焦的JPanel
。当您按下相关的键盘“方向”键之一,即A或D或S或W时,控制台将显示方向。按下任何其他键会导致STILL方向被写入控制台。请注意,我在各个方向上都使用了enum,而不是整数常量。import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class Screen01 extends JPanel implements Runnable {
public enum Directions {RIGHT, LEFT, UP, DOWN, STILL};
private static final int WIDTH = 300, HEIGHT = 300;
private Directions direction;
public Screen01() {
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
addKeyListener(new Key());
}
public void run() {
createAndDisplayGui();
}
private void createAndDisplayGui() {
JFrame frame = new JFrame("Screen");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(this, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private class Key implements KeyListener {
@Override
public void keyTyped(KeyEvent e) {
// Do nothing.
}
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_D:
direction = Directions.RIGHT;
break;
case KeyEvent.VK_A:
direction = Directions.LEFT;
break;
case KeyEvent.VK_W:
direction = Directions.UP;
break;
case KeyEvent.VK_S:
direction = Directions.DOWN;
break;
default:
direction = Directions.STILL;
}
System.out.println("Direction = " + direction);
}
@Override
public void keyReleased(KeyEvent e) {
// Do nothing.
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Screen01());
}
}
KeyListener
相关的问题,而无需对其进行“有时”工作的原因进行过多的黑客干预和抓挠]]Swing是单线程的。这意味着您应该注意从事件调度线程的上下文外部(直接或间接)更新UI状态,这还包括UI可能依赖的任何状态。