我正在尝试在需要数千次计算的JPanel上绘制图像,并且我希望为绘图的进展设置动画。即,不是一次完成所有100K的绘图迭代,然后重新绘制JPanel,我想在每次迭代后重新绘制,然后暂停几分之一秒,以便用户看到图像逐渐出现。但是,每次刷新JPanel都会删除以前的绘图,因此我的方法不起作用。如何在不复制第N次迭代的所有(1..N-1)计算的情况下执行此操作?
考虑这个例子:我希望“雪”逐渐出现在屏幕上。但是,此代码仅显示第100,000个“雪花”,因为每次调用repaint()时都会删除所有先前的雪花。
import javax.swing.*;
import java.awt.*;
import java.util.Random;
class spanel extends JPanel{
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawLine(snow.x, snow.y, snow.x, snow.y);
}
}
class snow extends Thread {
static int x,y;
Random r = new Random();
public void run(){
JFrame sboard = new JFrame();
sboard.setSize(600,600);
sboard.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
spanel mypanel = new spanel();
sboard.add(mypanel);
sboard.setVisible(true);
for (int i=0;i<100000;i++){
x=r.nextInt(600);
y=r.nextInt(600);
sboard.repaint();
try {
snow.sleep((long)10);
} catch (InterruptedException e) {};
}
}
}
public class SnowAnim {
public static void main(String[] args) {
(new snow()).start();
}
}
答案 0 :(得分:1)
Custom Painting Approaches显示了如何在BufferedImage上绘图。论坛中还有很多其他的例子。
此外,在制作动画时,您应该使用Swing Timer来安排动画。
答案 1 :(得分:1)
如何在不复制第N次迭代的所有(1..N-1)计算的情况下执行此操作?
将BufferedImage
添加到{{1}}。
答案 2 :(得分:0)
您应该在缓冲区上进行绘制,然后在paintComponent()中绘制缓冲区的当前状态;
你也可以跳过super.paintComponent(g);
的电话,但是你必须担心其他元素在你的面板中被视觉“卡住”。
答案 3 :(得分:0)
谢谢大家!我想到了。 BufferedImage解决了这个问题。为了记录,这是我更新的代码。它还实现了camickr的建议,即使用Swing计时器而不是线程来安排动画。我也做了一些美学上的改变,使输出看起来更像雪:-)再次感谢!
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.util.Random;
import java.awt.event.*;
class spanel extends JPanel{
int x,y,rad,i;
static Random r = new Random();
BufferedImage image;
Graphics2D g2d;
Timer timer;
spanel(){
image = new BufferedImage(600, 600, BufferedImage.TYPE_INT_ARGB);
g2d = (Graphics2D)image.getGraphics();
setBackground(Color.black);
g2d.setColor(Color.white);
i=0;
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
iterate();
}
};
timer = new Timer(10, listener);
timer.start();
}
public void iterate(){
x=r.nextInt(600);
y=r.nextInt(600);
rad=r.nextInt(5)+5;
g2d.fillOval(x, y, rad, rad);
repaint();
i++;
if (i==1000){timer.stop();}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(image,0,0,null);
}
}
public class SnowAnim {
public static void main(String[] args) {
JFrame sboard = new JFrame();
sboard.setSize(600,600);
sboard.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
spanel mypanel = new spanel();
sboard.add(mypanel);
sboard.setVisible(true);
}
}