我正在尝试使用 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(向下)更改,但它从来没有这样做。一段时间后,我意识到 keyPressed 方法出了问题,我只是不知道是什么。
最佳答案
您不需要单独的“游戏循环”线程。 Swing 是事件驱动的。当用户按下计算机键盘上的某个键时,将调用您的按键监听器代码。
正如MadProgrammer在他的comment to your question中提到的那样
modifying he state of the UI from outside the context of the EDT may cause painting issues
换句话说,Swing 是 single threaded该线程称为事件调度线程 (EDT),所有更改 GUI 的代码都应仅在 EDT 上执行。
下面的代码是一个独立的 Swing 应用程序,它显示可聚焦的 JPanel
。当您按下相关键盘“方向”键之一(即 A 或 D 或 S 或 W)时,控制台会显示方向。按任何其他键都会导致方向仍然写入控制台。请注意,我使用了 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());
}
}
关于java - KeyListener 方法 keyPressed 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61421299/