Nano Hash - криптовалюты, майнинг, программирование

Программа зависает во время Thread.sleep() и с таймером

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

Этот метод предназначен для постепенного изменения изображения, отображаемого в 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);
}

  • Осознаете ли вы, что спите (ширина * высота * k) секунд всего? Для изображения размером 256 x 256 с параметром k, равным 10, ваш код будет выполняться 7 дней. 19.10.2011

Ответы:


1

Никогда не используйте 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() );
    }
}
19.10.2011
  • спасибо за совет ... Как я могу установить таймер, чтобы ненадолго приостановить цикл? Я почти не знаком с таймерами... 19.10.2011
  • Вот почему я дал вам ссылку на учебник. Затем вы также можете поискать примеры на форуме или в Интернете. 19.10.2011
  • Я пытался использовать таймер, у меня была точно такая же проблема с зависанием... Разве я не реализовал это правильно? 19.10.2011
  • Это мое предположение. Чтобы использовать таймер, вам нужно будет реструктурировать свой код. У вас никогда не будет петли. Таймер — это цикл. Таймер будет поддерживать и обновлять переменные l, i, j. Таймер запускается вне кода цикла, а не внутри кода. Начните с простого примера, чтобы понять основы. Как я уже говорил в своем втором предложении, подход SwingWorker позволит вам сохранить циклическую структуру и функцию Thread.sleep(). 19.10.2011

  • 2

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

    19.10.2011
  • Это правда... Я изменил его. Спасибо за совет. Однако это не решает проблему. 19.10.2011

  • 3

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

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..