程序在Thread.sleep()和Timer期间冻结

原始问题:

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

在Event Dispatch Thread上执行代码时,切勿使用Thread.sleep()。

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

请参阅Swing教程中的部分:

  1. Swing中的并发性
  2. 如何使用计时器

或者,如果您不想使用Timer,那么您可以使用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次。

如果打算显示变形效果的渐进式动画,下面是我在使用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 = ((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); } }