程序在 Thread.sleep() 期间和计时器冻结

发布于 2024-12-10 13:31:05 字数 3136 浏览 0 评论 0原文

原始问题:

此方法应该将 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);
}

Original question:

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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

潇烟暮雨 2024-12-17 13:31:05

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

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

请参阅 Swing 教程中关于:

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

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

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

See the sections from the Swing tutorial on:

  1. Concurrency in Swing
  2. How to Use Timers

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.

Simple Timer example:

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() );
    }
}
叫思念不要吵 2024-12-17 13:31:05

k 上的循环应该是最外层的循环。现在您正在调用 Thread.sleep k*width*height 次。

The loop over k should be the outermost loop. Right now you are calling Thread.sleep k*width*height times.

烙印 2024-12-17 13:31:05

如果目的是显示变形效果的渐进动画,下面是我没有使用TimerThread.sleep()所做的测试代码,使用OP给出的最新变形代码:

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.JApplet;
import javax.swing.JFrame;


class MorphComponent extends Component {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private BufferedImage bi;
    private URL imageSrc1;
    private URL imageSrc2;     
    public MorphComponent(URL imageSrc1, URL imageSrc2) {
        this.imageSrc1 = imageSrc1;
        this.imageSrc2 = imageSrc2;     
        try {
            BufferedImage img1 = ImageIO.read(imageSrc1);
            //BufferedImage img2 = ImageIO.read(imageSrc2);
            int w = img1.getWidth(null);
            int h = img1.getHeight(null);
            bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics g = bi.getGraphics();
            g.drawImage(img1, 0, 0, null);

        } catch (IOException e) {
            System.out.println("Image could not be read");
            System.exit(1);
        }
    }

    public Dimension getPreferredSize() {
        return new Dimension(bi.getWidth(null), bi.getHeight(null));
    }


    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor(Color.white);
        g2d.fillRect(0,0, getWidth(), getHeight());
        try {
            BufferedImage img1 = ImageIO.read(imageSrc1);
            BufferedImage img2 = ImageIO.read(imageSrc2);
            int w = img1.getWidth(null);
            int h = img1.getHeight(null);        
            bi = morphImg(g, img1, img2, w, h, 10);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private long start = System.currentTimeMillis();

    public BufferedImage morphImg(Graphics gp, BufferedImage originalImage, BufferedImage morphImage, int width, int height, 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++) {
                    long elapsed = System.currentTimeMillis() - start;
                    //get color from original image
                    Color c = new Color(originalImage.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());

                    if( elapsed > 100 ) {
                        gp.drawImage(image2, 0, 0, null);
                        start = System.currentTimeMillis();
                        repaint();
                    }

                }
            }
        }
        return image2;
    }

}

public class MorphImageApplet extends JApplet {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    static String imageFileName1 = "image_1.jpg";
    static String imageFileName2 = "image_2.jpg";
    private URL imageSrc1;
    private URL imageSrc2;

    public MorphImageApplet () {
    }

    public MorphImageApplet (URL imageSrc1, URL imageSrc2) {
        this.imageSrc1 = imageSrc1;
        this.imageSrc2 = imageSrc2;
    }

    public void init() {
        try {
            imageSrc1 = new URL(getCodeBase(), imageFileName1);
            imageSrc2 = new URL(getCodeBase(), imageFileName2);
        } catch (MalformedURLException e) {
        }
        buildUI();
    }

    public void buildUI() {
        final MorphComponent st = new MorphComponent(imageSrc1, imageSrc2);
        add("Center", st);
    }

    public static void main(String s[]) {
        JFrame f = new JFrame("See Through Image");
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}
        });
        URL imageSrc1 = null;
        URL imageSrc2 = null;
        try {
             imageSrc1 = ((new File(imageFileName1)).toURI()).toURL();
             imageSrc2 = ((new File(imageFileName2)).toURI()).toURL();
        } catch (MalformedURLException e) {
        }
        MorphImageApplet sta = new MorphImageApplet(imageSrc1, imageSrc2);
        sta.buildUI();
        f.add("Center", sta);
        f.pack();
        f.setVisible(true);
    }
}

If the intention is to show progressive animation of the morph effect, below is the test code I did without using Timer or Thread.sleep(), using the latest morph code given by OP:

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.JApplet;
import javax.swing.JFrame;


class MorphComponent extends Component {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private BufferedImage bi;
    private URL imageSrc1;
    private URL imageSrc2;     
    public MorphComponent(URL imageSrc1, URL imageSrc2) {
        this.imageSrc1 = imageSrc1;
        this.imageSrc2 = imageSrc2;     
        try {
            BufferedImage img1 = ImageIO.read(imageSrc1);
            //BufferedImage img2 = ImageIO.read(imageSrc2);
            int w = img1.getWidth(null);
            int h = img1.getHeight(null);
            bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics g = bi.getGraphics();
            g.drawImage(img1, 0, 0, null);

        } catch (IOException e) {
            System.out.println("Image could not be read");
            System.exit(1);
        }
    }

    public Dimension getPreferredSize() {
        return new Dimension(bi.getWidth(null), bi.getHeight(null));
    }


    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor(Color.white);
        g2d.fillRect(0,0, getWidth(), getHeight());
        try {
            BufferedImage img1 = ImageIO.read(imageSrc1);
            BufferedImage img2 = ImageIO.read(imageSrc2);
            int w = img1.getWidth(null);
            int h = img1.getHeight(null);        
            bi = morphImg(g, img1, img2, w, h, 10);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private long start = System.currentTimeMillis();

    public BufferedImage morphImg(Graphics gp, BufferedImage originalImage, BufferedImage morphImage, int width, int height, 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++) {
                    long elapsed = System.currentTimeMillis() - start;
                    //get color from original image
                    Color c = new Color(originalImage.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());

                    if( elapsed > 100 ) {
                        gp.drawImage(image2, 0, 0, null);
                        start = System.currentTimeMillis();
                        repaint();
                    }

                }
            }
        }
        return image2;
    }

}

public class MorphImageApplet extends JApplet {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    static String imageFileName1 = "image_1.jpg";
    static String imageFileName2 = "image_2.jpg";
    private URL imageSrc1;
    private URL imageSrc2;

    public MorphImageApplet () {
    }

    public MorphImageApplet (URL imageSrc1, URL imageSrc2) {
        this.imageSrc1 = imageSrc1;
        this.imageSrc2 = imageSrc2;
    }

    public void init() {
        try {
            imageSrc1 = new URL(getCodeBase(), imageFileName1);
            imageSrc2 = new URL(getCodeBase(), imageFileName2);
        } catch (MalformedURLException e) {
        }
        buildUI();
    }

    public void buildUI() {
        final MorphComponent st = new MorphComponent(imageSrc1, imageSrc2);
        add("Center", st);
    }

    public static void main(String s[]) {
        JFrame f = new JFrame("See Through Image");
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}
        });
        URL imageSrc1 = null;
        URL imageSrc2 = null;
        try {
             imageSrc1 = ((new File(imageFileName1)).toURI()).toURL();
             imageSrc2 = ((new File(imageFileName2)).toURI()).toURL();
        } catch (MalformedURLException e) {
        }
        MorphImageApplet sta = new MorphImageApplet(imageSrc1, imageSrc2);
        sta.buildUI();
        f.add("Center", sta);
        f.pack();
        f.setVisible(true);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文