程序在 Thread.sleep() 和 Timer 期间冻结 [英] Program freezes during Thread.sleep() and with Timer

查看:24
本文介绍了程序在 Thread.sleep() 和 Timer 期间冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

原始问题:

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

This method is supposed to change the image being displayed on a JFrame gradually into another image. However, without some way to slow it down, it just seems to change from one image to the new image. In order to slow it down, I put in a Thread.sleep(1000) so the changes wouldn't happen instantly. However, with this line in there, my program freezes completely. No error message, no nothing. Can anyone please help me out? Suggest a better method to slow it down, or how this can be fixed.

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

For clarification: int k is the number of gradual steps in the change. k = 1 would be an instant change. Anything greater would be gradual changes. int l meanwhile controls the ratio of how much of each image is displayed.

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

更新代码:使用计时器也会导致程序冻结...我使用的方法不对吗?

UPDATED CODE: Using a Timer also causes the program to freeze...Am I not using it right?

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().

Never use Thread.sleep() when code is executing on the Event Dispatch Thread.

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

Instead you should use a Swing Timer to schedule your animation.

请参阅 Swing 教程中的部分:>

See the sections from the Swing tutorial on:

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

或者,如果您不想使用 Timer,那么您可以使用 SwingWorker(如并发教程中所述),然后在更改图像后直接发布()图像.然后您可以使用 Thread.sleep(),因为 SwingWorker 不在 EDT 上执行.

Or if you don't want to use a Timer, then you can use a SwingWorker (as described in the tutorial on concurrency) and then just publish() the image after you change it. Then you can use a Thread.sleep() since the SwingWorker doesn't execute on the 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() );
    }
}

这篇关于程序在 Thread.sleep() 和 Timer 期间冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆