我正在尝试用 Java 和 Swing 制作 Pong。但是,我有两个问题 - 一,屏幕上的矩形根本不移动,二,即使代码仍在运行,也会发生 NullPointerException。这是我的两个文件:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Pong extends JFrame implements KeyListener {
private static final long serialVersionUID = -5782301423436L;
JPanel panel;
Paddle paddle1;
public Pong() {
super("Pong");
panel = new JPanel();
this.add(panel);
super.setPreferredSize(new Dimension(800, 600));
super.setVisible(true);
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
super.pack();
addKeyListener(this);
paddle1 = new Paddle(100, 300);
}
public static void main(String[] args) {
@SuppressWarnings("unused")
Pong game = new Pong();
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, 800, 600);
g.setColor(Color.BLACK);
this.paddle1.draw(g);
}
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
// I've tested this part and the w and s key presses
// are still detected, but nothing happens. Why not?
public void keyPressed(KeyEvent keyEvent) {
int key = keyEvent.getKeyCode();
if (key == KeyEvent.VK_ESCAPE) {
this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
} else if (key == KeyEvent.VK_W) {
this.paddle1.up();
} else if (key == KeyEvent.VK_S) {
this.paddle1.down();
}
}
}
import java.awt.Graphics;
public class Paddle {
// Position of the paddle's center
int x;
int y;
public Paddle(int x, int y) {
this.x = x;
this.y = y;
}
public void draw(Graphics g) {
g.fillRect(this.x - 10, this.y - 40, 20, 80);
}
// Up is negative because Java coordinates
public void up() {
this.y -= 30;
}
public void down() {
this.y += 30;
}
}
我已经在 Pong 文件中测试了 keyPressed 方法,当按下 w 和 s 键时,它实际上会检测到它们(它会在控制台上打印一行)。我对 Java 图形非常陌生,这是我尝试创建的第一个不是从 YouTube 教程中复制粘贴的东西。我已经检查了我的代码大约一个小时,但找不到错误可能出在哪里。任何和所有的帮助将不胜感激。
最佳答案
我已经检查了代码,可以帮助您解决错误。
首先,您在此处展示了使用 JFrame Pong 的 Paint() 方法的 Paddle。您正在检测“W”和“S”键,并根据您编写的代码来更新 Paddle 类中的 y 坐标。
但是,这里的问题是,您只是更新 y 坐标。您不会再次使用新坐标绘制桨。因此,设置新的 y 值后,您应该再次绘制桨。 所以,在 keyPressed() 方法中,在
之后this.paddle1.up();
和
this.paddle1.down();
您应该再次调用 Paddle 类的 draw() 方法,该方法将在修改的位置绘制 Paddle。
在此draw()方法中,您将传递一个Graphics对象,它是当前JFrame Pong的图形配置。因此,可以使用 JFrame 的 getGraphics() 方法来获取。
因此,在 up() 或 down() 之后添加的行将是
this.paddle1.draw(getGraphics());
由于我们处理的是图形,因此一旦更改了 JFrame 图形中的某些内容,重新绘制 JFrame 也是正确的做法。如果您在 keyPressed() 方法中的 up() 和 down() 方法之后仅添加上述行,您将看到 Paddle 没有移动。其先前的绘制将保持原样,并且根据按下的键,新的桨将向上或向下绘制。因此,您将看到一条垂直条,而不是移动的桨。发生这种情况是因为我们正在修改图形,但没有再次绘制 JFrame。因此,它只会在 JFrame 中添加新矩形,并保持先前的不变。 因此,要摆脱这个问题,您应该使用 JFrame 的 repaint() 方法,以便它只绘制最新的屏幕。
因此,完整的 keyPressed() 方法如下:
@Override
public void keyPressed(KeyEvent keyEvent) {
int key = keyEvent.getKeyCode();
if (key == KeyEvent.VK_ESCAPE) {
this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
} else if (key == KeyEvent.VK_W) {
this.paddle1.up();
this.paddle1.draw(getGraphics());
repaint();
} else if (key == KeyEvent.VK_S) {
this.paddle1.down();
this.paddle1.draw(getGraphics());
repaint();
}
}
所以,现在在检测到正确的按键后,它会再次绘制桨并 之后也会丢弃之前的代码,这样当您运行此代码时,您将能够看到桨按照按下的键移动。
现在,关于 NullPointerException。我尝试运行此代码,但无法重现此类异常。因此,在尝试建议的代码后,如果遇到 NPE,可以更新堆栈跟踪来解决问题。
我已经阅读了这些评论,它们非常有用。请检查解释收听关键事件的更好方法的链接。
谢谢。
关于java - 如何用java.Swing移动乒乓 Racket ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60472083/