Программа зависает во время 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 = ((kl)*c.getRed()/k) + (l*c2.getRed()/k); int g = ((kl)*c.getGreen()/k) + (l*c2.getGreen()/k); int b = ((kl)*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 = ((kl)*c.getRed()/k) + (l*c2.getRed()/k); int g = ((kl)*c.getGreen()/k) + (l*c2.getGreen()/k); int b = ((kl)*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 (), когда код выполняется в Thread Dispatch Thread.

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

См. Разделы из руководства Swing :

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

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

Если целью является показать прогрессивную анимацию эффекта морфинга, ниже приведен тестовый код, который я использовал без использования 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 = ((kl)*c.getRed()/k) + (l*c2.getRed()/k); int g = ((kl)*c.getGreen()/k) + (l*c2.getGreen()/k); int b = ((kl)*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); } } 
  • исключения try-catch в Swift
  • Правильно Попробуйте ... Синтаксис Catch с использованием Async / Await
  • Как я могу предотвратить сбой node.js? try-catch не работает
  • Стоит ли использовать блоки try-catch, даже если исключение никогда не бросается?
  • Будет ли код в объявлении finally загораться, если я верну его значение в блоке Try?
  • Как работают исключения (за кадром) в c ++
  • catch исключение указателем в C ++
  • Попробуйте с ресурсами против Try-Catch
  • «Плохо» использовать try-catch для управления streamами в .NET?
  • Почему пустые блоки блокировки имеют плохую идею?
  • Могу ли я поймать несколько исключений Java в одном и том же предложении catch?
  • Давайте будем гением компьютера.