【发布时间】:2020-05-22 17:15:42
【问题描述】:
在 Head First Java 书上,我们看到了一些小动画,我正在尝试绘制一个描绘对角线的动画。我这样做是通过使用 paintComponent() 方法并在 x,y 处绘制一个椭圆(每次通过循环更新的值)。为什么我会丢失之前绘制的椭圆?根据这本书,我应该在屏幕上涂上之前绘制的椭圆并没有丢失的地方。这应该需要通过在每次调用 repaint() 时向 paintComponent() 方法添加一个白色背景来修复,但我没有得到“错误”。 为什么会这样?如何在面板上保留先前绘制的椭圆?
使用 JDK 13.0.2 和 Mac OSX Catalina
import javax.swing.*;
import java.awt.*;
public class SimpleAnimation {
int x = 70;
int y = 70;
public static void main(String[] args) {
SimpleAnimation gui = new SimpleAnimation();
gui.go();
}
public void go() {
JFrame frame = new JFrame();
MyDrawPanel drawPanel = new MyDrawPanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(drawPanel);
frame.setSize(300,300);
frame.setVisible(true);
for (int i = 0; i < 130; i++) {
x++;
y++;
drawPanel.repaint();
try {
Thread.sleep(25);
} catch (Exception ex){};
}
}
class MyDrawPanel extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.orange);
g.fillOval(x,y,50,50);
}
} // close inner class
} // close outer class
【问题讨论】:
-
假设你是从 EDT 运行的(如果你还没有的话,你应该这样做),你肯定不想在摇摆应用程序中使用
Thread.sleep()。相反,请使用摇摆Timer制作动画。 -
还没学过线程。这是防止椭圆形涂抹的原因吗?
-
@vader,不,线程是一个单独的命令执行序列。想想几个处理器内核,每个内核都有自己必须运行的命令列表(但在 Java 中,它是模拟和调度的,而且......你明白了)。大多数 Java 应用程序都有多个,尤其是 Swing 有一个称为“UI 线程”的东西,它负责绘制应用程序,理想情况下你不应该让它休眠,因为这样 UI 就会变得无响应。
-
您发布的代码不完整。我们不知道 go() 方法是如何被调用的,所以我们不知道您的代码是否在 EDT 上执行。如果代码在 EDT 上执行,那么您会导致 EDT 进入睡眠状态,这意味着框架无法自行重绘。如果它不在 EDT 上,那么您应该看到圆圈的“涂抹”。但如果没有可执行代码,我们无法确定您在做什么。
-
别告诉我们。发布您正在执行的确切代码。所以我们可以复制/粘贴/编译/文本。这称为minimal reproducible example。每个问题都应该发布一个“MRE”。
标签: java swing jpanel paintcomponent