在Java中连续复杂图像的动画

时间:2013-04-12 22:55:43

标签: java swing drawing jpanel java-2d

我正在尝试在需要数千次计算的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();
    }
}

4 个答案:

答案 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);
    }
}