Программа зависает во время Thread.sleep () и с таймером - PullRequest
0 голосов
/ 19 октября 2011

Оригинальный вопрос:

Этот метод должен постепенно преобразовывать изображение, отображаемое в JFrame, в другое изображение. Однако, без какого-либо способа замедлить его, кажется, что он просто меняется с одного изображения на новое. Чтобы замедлить его, я добавил Thread.sleep (1000), чтобы изменения не происходили мгновенно. Однако с этой строкой моя программа полностью зависает. Нет сообщения об ошибке, нет ничего. Кто-нибудь может помочь мне? Предложите лучший способ замедлить его, или как это можно исправить.

Для пояснения: int 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);
}

Ответы [ 3 ]

5 голосов
/ 19 октября 2011

Никогда не используйте Thread.sleep () при выполнении кода в потоке диспетчеризации событий.

Вместо этого следует использовать таймер Swing для планирования анимации.

См. Разделы из Swing tutorial on:

  1. Параллелизм в Swing
  2. Как использовать таймеры

Или если вы не хотите использоватьТаймер, затем вы можете использовать SwingWorker (как описано в руководстве по параллелизму), а затем просто опубликовать () изображение после его изменения.Затем вы можете использовать Thread.sleep (), поскольку SwingWorker не выполняется в EDT.

Пример простого таймера:

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

public class TimerTime extends JFrame implements ActionListener
{
    JLabel timeLabel;

    public TimerTime()
    {
        timeLabel = new JLabel( new Date().toString() );
        getContentPane().add(timeLabel, BorderLayout.NORTH);
    }

    public void actionPerformed(ActionEvent e)
    {
        timeLabel.setText( new Date().toString() );
    }

    public static void main(String[] args)
    {
        TimerTime frame = new TimerTime();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setVisible(true);

        int time = 1000;
        javax.swing.Timer timer = new javax.swing.Timer(time, frame);
        timer.setInitialDelay(1);
        timer.start();
    }
}
1 голос
/ 19 октября 2011

Цикл над k должен быть самым внешним. Прямо сейчас вы звоните Thread.sleep k * width * height times.

0 голосов
/ 19 октября 2011

Если предполагается показать прогрессивную анимацию эффекта морфа, ниже приведен тестовый код, который я сделал без , используя Timer или Thread.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);
    }
}
...