0

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

4 回答 4

1

自定义绘画方法展示了如何在 BufferedImage 上绘画。论坛里还有很多其他的例子。

此外,在制作动画时,您应该使用 Swing Timer 来安排动画。

于 2013-04-13T00:20:00.923 回答
1

如何在不复制第 N 次迭代的所有 (1..N-1) 计算的情况下做到这一点?

BufferedImage本例所示,将它们添加到 a中。

于 2013-04-13T01:11:15.070 回答
0

您可能应该在缓冲区上进行绘画,然后在 paintComponent(); 中绘制缓冲区的当前状态;

您也可以跳过对 的调用super.paintComponent(g);,但是您将不得不担心其他元素会在视觉上“卡住”在您的面板中。

于 2013-04-12T23:03:50.870 回答
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);
    }
}
于 2013-04-13T17:20:27.873 回答