Il programma si blocca durante Thread.sleep () e con Timer

Domanda originale:

Questo metodo dovrebbe cambiare gradualmente l’immagine visualizzata su un JFrame in un’altra immagine. Tuttavia, senza alcun modo di rallentarlo, sembra proprio che passi da un’immagine alla nuova immagine. Per rallentarlo, ho inserito Thread.sleep (1000) in modo che le modifiche non si verifichino all’istante. Tuttavia, con questa linea in là, il mio programma si blocca completamente. Nessun messaggio di errore, niente di niente. Per favore qualcuno può aiutarmi? Suggerisci un metodo migliore per rallentarlo o come può essere risolto.

Per chiarimenti: int k è il numero di passaggi graduali nel cambiamento. k = 1 sarebbe un cambiamento istantaneo. Qualunque cosa maggiore sarebbero cambiamenti graduali. int intanto controlla il rapporto tra la quantità di ciascuna immagine visualizzata.

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

CODICE AGGIORNATO: L’uso di un timer fa sì che il programma si blocchi … Non lo sto usando giusto?

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

Non utilizzare mai Thread.sleep () quando il codice è in esecuzione nel thread di invio eventi.

Invece dovresti usare un timer Swing per programmare la tua animazione.

Guarda le sezioni del tutorial Swing su:

  1. Concorrenza in swing
  2. Come usare i timer

Oppure, se non si desidera utilizzare un timer, è ansible utilizzare uno SwingWorker (come descritto nel tutorial sulla concorrenza) e quindi pubblicare () l’immagine dopo averla modificata. Quindi puoi usare Thread.sleep () poiché SwingWorker non viene eseguito sull’EDT.

Esempio di Simple Timer:

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

Il ciclo su k dovrebbe essere il ciclo più esterno. In questo momento stai chiamando Thread.sleep k * width * height times.

Se l’intenzione è quella di mostrare l’animazione progressiva dell’effetto morph, sotto c’è il codice di prova che ho fatto senza usare Timer o Thread.sleep() , usando l’ultimo codice di morph dato da 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.MalformsdURLException; 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 (MalformsdURLException 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 (MalformsdURLException e) { } MorphImageApplet sta = new MorphImageApplet(imageSrc1, imageSrc2); sta.buildUI(); f.add("Center", sta); f.pack(); f.setVisible(true); } }