所以我用 Java 创建了一个小窗口,上面有一个球在上面弹跳,并尝试调试和观察程序的工作情况。这是该问题的重要代码:
public class Ball {
private static final int SPEED = 2;
private int x = 0, y = 0;
private int xInc = SPEED, yInc = SPEED;
-> public void paint(Graphics2D g) {
g.fillOval(x, y, 30, 30);
}
}
public class Game extends JPanel {
Ball gameBall = new Ball();
public void paint(Graphics g) {
super.paint(g); // cleans the panel
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
gameBall.paint(g2d);
}
public void updateBall() {
gameBall.move(this.getWidth(), this.getHeight());
}
public static void main(String[] args) {
JFrame mainFrame = new JFrame("Simple Pong");
mainFrame.setSize(400, 400);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Game gamePanel = new Game();
mainFrame.add(gamePanel);
mainFrame.setVisible(true);
while (true) {
try {
gamePanel.updateBall();
gamePanel.repaint();
Thread.sleep(10);
} catch (InterruptedException e) {
System.out.println(e);
System.exit(1);
}
}
}
}
我为Ball的paint方法的入口设置了一个方法指针,认为这会导致每次调用repaint()方法时程序停止,因为我认为它调用了paint方法。然后,我可以观察球一次移动一个增量,而不是在重绘方法所在的位置放置一个线指针。
当我这样做时,程序不会随着球位置的每次更新而停止,而是以看似随机的增量停止。球将接近边缘,然后在中间必须发生许多内线调用。
问题:重绘方法是否总是调用轻量级容器的绘制方法?如果是这样,为什么调试器不会随着球的每次增量而停止,而有时只是停止显示新位置?显然,如果球在运行时在屏幕上平滑移动,则某些东西正在将球对象完全按照我想要的方式绘制到我的游戏面板上。
注意:如果我们在 Game 的绘制方法的入口放置一个方法断点,也会发生同样的情况,我扩展了 JPanel,并且将球绘制到了该方法上。
最佳答案
repaint
不会直接调用 paint
。 它只是设置一个变量,以便 Swing 在某个时刻记住调用 油漆
。
现在,你了解线程吗?因为这里发生的事情的解释涉及到线程。
与 Swing 相关的所有事情通常都在一个线程上运行,称为“事件线程”。特别是,paint
在事件线程上被调用。
main
在称为“主线程”的线程上调用。主线程不是事件线程。您的 main
方法移动球(通过调用 updateBall
间接实现)。主线程的代码大致是“移动球,设置‘稍后重新绘制’变量,重复”。
当断点被击中时,只有击中断点的线程才会暂停。这意味着事件线程已暂停。更新球位置的主线程继续运行。当您认为程序暂停时,球的位置不断更新(因为实际上只有一个线程暂停)。
当您取消暂停事件线程时,事件线程将返回执行其正在执行的操作(即绘画)。因为,到目前为止,“稍后重新绘制我”变量将被设置,它将再次绘制游戏面板 - 但这次球将移动很远。
关于java - JPanel repaint()方法及调试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26749166/