java - 程序在 Thread.sleep() 期间和计时器卡住

标签 java try-catch sleep freeze bufferedimage

原始问题:

此方法应该将 JFrame 上显示的图像逐渐更改为另一个图像。然而,如果没有某种方法减慢它的速度,它似乎只是从一张图像变成了新图像。为了减慢速度,我放入了 Thread.sleep(1000),这样更改就不会立即发生。然而,有了这一行,我的程序就完全卡住了。没有错误消息,什么也没有。有人可以帮我吗?建议一种更好的方法来减慢速度,或者如何解决这个问题。

澄清一下:int k 是变化的渐进步骤数。 k = 1 将是瞬时变化。任何更大的改变都将是渐进的。 int l 同时控制每张图像显示的比例。

public void morphImg(int width, int height, BufferedImage morphImage, int k) {
    //creates new image from two images of same size
    BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            //get color from original image
            Color c = new Color(image.getRGB(i, j));

            //get colors from morph image
            Color c2 = new Color(morphImage.getRGB(i, j));

            for (int l = 1; l <= k; l++) {
                //gets colors at different stages
                int r = ((k-l)*c.getRed()/k) + (l*c2.getRed()/k);
                int g = ((k-l)*c.getGreen()/k) + (l*c2.getGreen()/k);
                int b = ((k-l)*c.getBlue()/k) + (l*c2.getBlue()/k);   
                Color newColor = new Color(r, g, b);
                //set colors of new image to average of the two images
                image2.setRGB(i, j, newColor.getRGB());

                //display new image
                try {
                    imageLabel.setIcon(new ImageIcon(image2));
                    Thread.sleep(1000);
                }
                catch (InterruptedException e){
                    System.out.println("Exception caught.");
                }
            }
        }
    }

    //sets modified image as "original" for further manipulation
    setImage(image2);
}

更新的代码:使用计时器也会导致程序卡住...我没有使用它吗?

public void morphImg(int width, int height, BufferedImage morphImage, int k) {
    //creates new image from two images of same size
    final BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    for (int l = 1; l <= k; l++) {
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                //get color from original image
                Color c = new Color(image.getRGB(i, j));

                //get colors from morph image
                Color c2 = new Color(morphImage.getRGB(i, j));

                //gets colors at different stages
                int r = ((k-l)*c.getRed()/k) + (l*c2.getRed()/k);
                int g = ((k-l)*c.getGreen()/k) + (l*c2.getGreen()/k);
                int b = ((k-l)*c.getBlue()/k) + (l*c2.getBlue()/k);   
                Color newColor = new Color(r, g, b);

                //set colors of new image to average of the two images
                image2.setRGB(i, j, newColor.getRGB());
                //display new image

                imageLabel.setIcon(new ImageIcon(image2));
                final Timer t = new Timer(500,null);
                t.setInitialDelay(500);
                t.start();
            }
        }
    }

    //sets modified image as "original" for further manipulation
    setImage(image2);
}

最佳答案

当代码在事件调度线程上执行时,切勿使用 Thread.sleep()。

相反,您应该使用 Swing Timer 来安排动画。

请参阅 Swing tutorial 中的部分上:

  1. Swing 中的并发
  2. 如何使用计时器

或者,如果您不想使用计时器,则可以使用 SwingWorker(如并发教程中所述),然后在更改图像后发布()图像。然后您可以使用 Thread.sleep(),因为 SwingWorker 不会在 EDT 上执行。

简单的计时器示例:

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;

public class TimerTime extends JPanel implements ActionListener
{
    private JLabel timeLabel;
    private int count = 0;

    public TimerTime()
    {
        timeLabel = new JLabel( new Date().toString() );
        add( timeLabel );

        Timer timer = new Timer(1000, this);
        timer.setInitialDelay(1);
        timer.start();
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        //  Update the time

        timeLabel.setText( new Date().toString() );
        count++;

        //  Stop after 10 events have been generated

        if (count == 10)
        {
            Timer timer = (Timer)e.getSource();
            timer.stop();
            System.out.println( "Timer stopped" );
        }
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("TimerTime");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new TimerTime() );
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
    }
}

关于java - 程序在 Thread.sleep() 期间和计时器卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7816585/

相关文章:

java - 更新 Arraylist java 中的特定对象项

java - 在 Android Studio 中使用 OpenCV native 代码

java - Spring Hello World Web 应用程序

python - 为什么在 Python 的 try/except 构造中使用 else?

java - android - 处理异常以更新 UI

java - 线程中的 sleep 和连接输出

java - 如何使用 BoxLayout 让组件与 JPanel 中的顶部对齐?

Python 2.7 - Linux - 无限循环,放弃 CPU 给其他线程/进程

Java - 访问静态方法 sleep - 怎么了?

javascript - 为什么 `finally` 中的返回覆盖 `try` ?