方法减慢执行paintComponent()

时间:2014-09-17 16:12:42

标签: java multithreading swing animation swingworker

我有一个小问题。在动画期间执行方法paintComponent()时,我必须不断更新变量bgImage。但这需要花费很多时间,因此动画会变慢。

带有问题的代码块:

public class ProblemClass extends JComponent {
    private static final int FRAME_FREQUENCY = 30;
    private final Timer animationTimer;

    public ProblemClass() {
        this.animationTimer = new Timer(1000 / FRAME_FREQUENCY, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                repaint(); // When the animation started is often invoked repaint()
            }
        });
    }

    // Other code...

    /** 
     * Start animation from another class
     */
    public void startAnimation() {
        this.animationTimer.start();
    }

    @Override 
    protected void paintComponent(Graphics g) { 
        // GraphicsUtils.gaussianBlur(...) it's a long-time operation
        BufferedImage bgImage = GraphicsUtils.gaussianBlur(AnotherClass.getBgImage()); 
        g2.drawImage(bgImage, 0, 0, null); 

        // Other code...
    }
}

我在互联网上读到我需要在并行线程(SwingWorker)中运行长任务,但我不知道如何在我的情况下执行它。我该如何解决这个问题?

P.S。对不起我的英语不好,这不是我的第一语言。

3 个答案:

答案 0 :(得分:1)

每次生成新的背景图像然后模糊它时,没有通用的方法来解决这个问题。 GaussianBlur 是一个缓慢的操作,句号。

如果 AnotherClass.getBgImage()从预定义的图像集传递图像,则将模糊一次应用于集合中的每个图像问题消失了。

如果您动态地在AnotherClass.getBgImage()中创建图像,那么可能能够通过更改图像创建来加速它以创建模糊图像开始。根据创建图像所做的操作,这可能是可行的,也可能是不可行的。

如果上述两种方法都没有解决,则需要研究其他选项以生成更快的模糊图像;有更简单的模糊方法,通常更快,但看起来有点像高斯。

你看,这一切归结为在性能关键路径上反复调用GaussianBlur。

答案 1 :(得分:1)

您要做的最好的事情是在paint方法之外进行图像更新,并且只在新图像准备就绪时重绘。获取现有代码,并为图像添加持久性引用,该引用将被绘制到JComponent每个绘制方法上。然后让你的动画计时器执行高斯模糊并更新你的图像。

public class ProblemClass extends JComponent {
    private static final int FRAME_FREQUENCY = 30;
    private final Timer animationTimer;

    //persistent reference to the image
    private BufferedImage bgImage;

    public ProblemClass() {
        this.animationTimer = new Timer(1000 / FRAME_FREQUENCY, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //Update the image on each call before repainting
                bgImage = GraphicsUtils.gaussianBlur(AnotherClass.getBgImage());
                repaint();
            }
        });
    }

    /** 
     * Start animation from another class
     */
    public void startAnimation() {
        this.animationTimer.start();
    }

    @Override
    protected void paintComponent(Graphics g2) {
        g2.drawImage(bgImage, 0, 0, null);

        // Other code...
    }
}

答案 2 :(得分:0)

你应该从画家那里提取逻辑。画家被称为有约束力,应该执行得非常快。

  BufferedImage bgImage = GraphicsUtils.gaussianBlur(AnotherClass.getBgImage()); 

这条线必须每次都执行?也许你可以使用一个字段来存储图像,画家可以只是图像,而不是每次都应用高斯布尔。

试试这个:     公共类ProblemClass扩展了JComponent {

    private static final int FRAME_FREQUENCY = 30;
    private final Timer animationTimer;
    private final BufferedImage bgImage;

    public ProblemClass() {
        bgImage = GraphicsUtils.gaussianBlur(AnotherClass.getBgImage());
        this.animationTimer = new Timer(1000 / FRAME_FREQUENCY, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                repaint(); // When the animation started is often invoked repaint()
            }
        });
    }

        // Other code...
    /** 
     * Start animation from another class
     */
    public void startAnimation() {
        this.animationTimer.start();
    }

    @Override
    protected void paintComponent(Graphics g2) {
        // GraphicsUtils.gaussianBlur(...) it's a long-time operation
        g2.drawImage(bgImage, 0, 0, null);

        // Other code...
    }
}