AWT中图像的异步加载和等待图像的完全加载
图像的异步加载
图像的加载和显示是异步进行的,图像 的生产者(ImageProducer)传递给图像的消费者(ImageConsumer)一个与图像相关的位,因为图像的生产过程是一个异步行为,所以 AWT 也提供一个图像观察(ImageObserver),用来监视图像生产者的图像生产过程。
因为 java.awt.Component 实现 ImageObserver 接口,所以 AWT 中每个构件都是ImageObserver ,当一个给定的 ImageProducer 采取异步操作时,这个 ImageObserver 可以选择是否被更新。
现在看一个例子:import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;
public class ImageTestAppletSimple2
extends Applet {
private Image im;
public void init() {
im = getImage(getCodeBase(), " lena.jpg " );
}
public void paint(Graphics g) {
System.out.println( " drawing image " );
System.out.println(g.drawImage(im, 0 , 0 , this ));
}
}
当这个 Applet 第一次被调用时,将打印出下面的结果:
drawing image...
false
drawing image...
false
drawing image...
false
drawing image...
true
执 行结果说明 drawImage() 在第一次被调用时,没有图像被加载,drawImage() 只是向和图像相关的 ImageProducer 注册 ImageObserver,图像被完全加载前 drawImage() 方法返回 false 直到图像被完全加载返回 true。
当 drawImage() 返回之后,只要有图像的新的部分被加载,ImageObserver 中的 imageUpdate() 方法就会被调用。当 ImageObserver 是 AWT 构件时,Component.imageUpdate() 调用 repaint() 方法清除构件背景并调用 paint() 方法重绘刚刚得到的图像位。重复循环,ImageProducer 加载图像的下一块,调用 ImageObserver 的 imageUpdate()。当图像被完全加载时,ImageProducer 停止调用 ImageObserver 的 imageUpdate(),循环中断。
load -> imageUpdate() -> repaint() -> update() -> paint()
等待图像的完全加载
上面的例子介绍了图像的异步加载,现在介绍2个方法使图像完全加载前不显示。
·重载 ImageObserver 中的 imageUpdate() 方法,使其在图像完全加载前不调用 repaint()。
import java.awt.Graphics;
import java.awt.Image;
public class ImageTestAppletWithUpdate
extends Applet {
private Image im;
public void init() {
im = getImage(getCodeBase(), " lena.jpg " );
}
public void paint(Graphics g) {
g.drawImage(im, 0 , 0 , this );
}
public boolean imageUpdate(Image image, int flags, int x, int y, int w, int h) {
System.out.println( " imageUpdate():x= " + x + " ,y= " + y + " ,w= " + w + " ,h= " +
h);
if ( (flags & ALLBITS) == 0 ) {
return true ; // need more updates
}
else {
repaint();
return false ; // image is fully loaded
}
}
}
使用 java.awt.MediaTracker 类跟踪图像的加载,不必重载 imageUpdate() 方法。
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
public class ImageTestAppletWithMediaTracker
extends Applet {
private Image im;
public void init() {
im = getImage(getCodeBase(), " lena.jpg " );
MediaTracker tracker = new MediaTracker( this );
tracker.addImage(im, 0 );
try {
tracker.waitForID( 0 );
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print( " Image width = " + im.getWidth( this ));
System.out.println( " height = " + im.getHeight( this ));
}
public void paint(Graphics g) {
g.drawImage(im, 0 , 0 , this );
}
}
我们可以把使用 java.awt.MediaTracker 类将图像完全加载的方法包装成一个实用方法
* 使用 java.awt.MediaTracker 将图像完全加载。
* @param component Component
* @param img Image
*/
public static void waitForImage(Component component, Image img) {
MediaTracker tracker = new MediaTracker(component);
try {
tracker.addImage(img, 0 );
tracker.waitForID( 0 );
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}