使用MediaTracker加载并显示图像

来源:互联网 发布:lic授权软件破解 编辑:程序博客网 时间:2024/06/05 17:38

原文链接:http://blog.163.com/fan_yishan/blog/static/47692213200832003827161/

上节我们阐述了两种加载并显示图像的方法,但是采用异步的方式,即程序在后台完成图像的加载和显示,而主进程继续执行。这种情况可能在图像还未被完全加载完毕时造成不完整的显示。在某些情况下,我们需要在图像完全加载完毕后再进行显示,要得到这种功能就需要了解本节介绍的另外一种加载图像的方法,即调用媒体跟踪器(Media Tracker)来加载图像。

媒体跟踪器是MediaTracker类型的对象,专门用来跟踪图像的加载。这个类在java.awt包中定义,目前只管理图像的载入,以后可能会扩展其功能用来跟踪其他类型的媒体资源的加载。MediaTracker只有一个构造器,需要一个组件引用的参数,这个组件对象就是装入图像的组件。表2.21列出了媒体跟踪器的构造器及其相关方法。

表2.21  媒体跟踪器的构造器及其相关方法

public MediaTracker(Component comp)

构造器:接收一个用于加载图像的Component对象

public void addImage(Image image, int id)

续表 

Image类的对象image添加到当前媒体跟踪器要追踪的图像列表中,整型对象id表示该image的标识

public void waitForAll()

初始化加载过程并等待所有被跟踪的图像加载

public boolean waitForAll(long ms)

指定初始化加载过程并等待图像加载的时间,时间用毫秒表示

Public boolean checkID(int id)

检查指定的标识为idImage对象image是否加载完毕,如果已经加载完毕,则返回真

Public boolean checkAll()

检查所有被跟踪的Image对象image是否加载完毕,如果已经加载完毕,则返回真

Public boolean isErrorAny()

检查所有被跟踪的Image对象image的错误状况,没有错误则返回假

Public boolean isErrorID(int id)

检查指定的标识为idImage对象image在加载过程中是否发生错误,没有错误则返回假

媒体跟踪器的使用是在调用getImage()方法,获得对Image的对象引用后,调用跟踪器的addImage()方法就将Image对象传递给媒体跟踪器。addImage方法有两个参数:要跟踪的图像的引用,以及用来跟踪图像的int类型的标识。媒体跟踪器可以同时跟踪多个图像,该标识决定被加载图像的优先级。

程序MediaTrackerApplet.java(\chap02\Fig2.11\Fig2.11_02)演示了如何在Applet中调用MediaTracker类以及跟踪图像,运行结果如图2.43所示。

程序第9行~第11行:

private Image[] images = new Image[3];

private Image bg; // 背景图像

private MediaTracker mt = null;

声明了1个Image类的数组对象images,其中包含3个image对象,1个Image类的对象bg,表示本Applet将要加载的背景图像,还声明了一个MediaTracker类的对象mt。

程序第14行~第27行,在init方法内,对上述变量进行初始化。

程序第16行:

bg = getImage(getCodeBase(), "images/background.gif");

用Applet类getImage方法得到一个Image类的对象引用,并传递给Applet。注意,在getImage的方法内,第2个参数的使用方法:

"images/background.gif"

表示图像文件的位置在Java Applet当前目录下的images子目录中,因此这里表示加载当前目录中的images子目录下的background.gif图像文件。

程序第19行:

mt = new MediaTracker(this);

初始化MediaTracker的实例mt。MediaTracker只有一个构造器,需要一个组件引用的参数,这个组件对象就是装入图像的组件。这里的this表示本容器,也就是在本Applet中创建图像。

程序第20行:

mt.addImage(bg, 0);

使用MediaTracker类的addImage方法,指定要跟踪的图像对象。媒体跟踪器可以同时跟踪多个图像,多个图像可以拥有相同的标识,标识的值决定加载图像的优先级,具有相对较低标识值的图像优先加载。这里,图像bg的标识指定为0。

程序第22行~第25行:

for (int i = 0; i < images.length; i++)   

{

   images[i] = getImage(getCodeBase(), "images/logo" + (i + 1) + ".jpg");

   mt.addImage(images[i], i + 1);

}

使用了一个循环,在用getImage方法获得图像的引用后,将当前目录下的images子目录中logo1.jpg、logo2以及logo3.jpg图像文件,依次添加到当前媒体跟踪器mt要跟踪的图像列表中。标识在这里分别设定为1、2、3。

init方法结束,进入paint方法中。

程序第32行~第40行:

try

{

   mt.waitForAll();

}

catch (InterruptedException e)

{

   System.out.println(e);

   return ;

}

程序在第34行,调用waitForAll方法初始化加载过程,并等待所有被跟踪的图像加载完毕后返回。如果要加载某个特定标识的图像对象,可以调用跟踪器的waitForID方法,并传递一个标识给该方法,开始加载与某个特定标识相关的所有图像对象,并等待所有与该标识相关的图像加载完成后才返回。例如,希望跟踪标识为1的图像,在上面的语句块中,只需要更改程序第34行:

mt.waitForID(1);

如果我们只希望跟踪某一个特定的图像对象,就赋予该媒体跟踪器中所跟踪的每个图像对象都具有一个惟一的标识。这样,一旦出现异常,我们可以通过相应的方法获得出错图像的标识,从而找到发生错误的地方。

这里介绍的waitForID和waitForAll方法将无限期进行等待。因为这些方法可能会抛出异常,所以将其放入一个try…catch语句块中。还有另外一个版本的waitForAll方法,该方法需要一个长整型变量,指定初始化加载过程以及等待图像加载的时间,时间用毫秒表示,由这个长整型的参数决定。但是使用这种方法,我们并不知道在该方法返回时,图像是否真的装载完毕了,还是等待的时间到了;也许图像早就加载完毕了,但因为设置的等待时间还没有结束,因此媒体跟踪器仍旧在等待,这样会严重浪费系统资源。所以我们推荐使用前面介绍的第1和第2种方法,而不要随意使用需要接收一个等待时间参数的waitForAll方法。

如果waitForID和waitForAll方法在无限期的等待中抛出异常,将被程序第36行~第40行的catch语句块所捕获,然后在命令控制台输出一条有关的异常信息,之后,主线程返回,Applet上没有任何显示。

waitForAll方法执行完毕后,虽然所有被跟踪的图像都已经加载完毕,但并不说明这些图像的加载过程中没有任何错误(例如,图像的路径有错、或者图像的文件名有误、或者文件名和路径都正确,但却是Java不支持的图像格式),所以,我们必须明确地检查错误,因此程序第42行~第53行的代码就负责此项检查工作:

if (mt.isErrorAny())

{

   for (int i = 0; i <= 4; i++)

   {

       if (mt.isErrorID(i))

       {

        g.drawString("图像产生错误状况!文件标志为:" + i, 10, 40 + 20 * i);

       }

   }

return ;

}

程序第42行,调用了isErrorAny方法,用来检查并确定任何被追踪的图像是否产生了错误。如果方法返回false,则说明没有错误发生;如果图像产生了错误,isErrorAny方法返回真。我们在程序第44行~第49行的代码中,对其进行进一步的检查。

程序第44行~第50行,编写了一段循环代码来检查并确定到底是哪一个被追踪的图像产生了错误。程序第46行,我们将循环语句中的局部变量i作为参数并调用isErrorID方法。如果isErrorID方法返回true,则说明至少在加载一个图像标志与变量i相关的图像发生了错误。因为每个图像都指定了惟一的标识,所以一旦发生错误,可以轻松地找到错误的图像。找到发生错误的图像后,程序将在Applet上绘制出一条与该错误相关的信息。

当确定图像的加载没有错误时,就可以显示这些图像了。

程序第55行:

g.drawImage(bg, 0, 0, this);

我们前面介绍过的Graphics类的dwawImage方法,在Applet上绘制图像bg,如图   2.43①所示。

图像bg(background.gif)的宽度和高度分别是565磅和470磅。为达到将该图作为Applet背景的目的,在调用MediaTrackerApplet.class的HTML文档中,我们指定该Media TrackerApplet.class的宽度和高度正好与图像bg(background.gif)的宽度和高度相同。例如,MediaTrackerApplet.html文档的第4行~第5行所示:

<APPLET CODE = "MediaTrackerApplet.class" WIDTH = "565" HEIGHT = "470">

</APPLET>

程序第57行以及第59行:

g.setFont(new Font("汉真广标", Font.PLAIN, 30));

g.drawString("MediaTracker 的使用", 15, 30);

用“汉真广标”(30磅,普通风格)这种字体在Applet上的坐标(15,30)处绘制文本“MediaTracker的使用”。Java的绘图模式默认为覆盖模式,所以,“MediaTracker的使用”这段文本将显示在已经绘制完成的图像bg上,见图2.43②所示。反之,如果程序第57、59行的位置互换,将无法看到文本“MediaTracker的使用”,因为图像对象bg将它覆盖了。

程序第61行~第64行:

for (int i = 0; i < 3; i++)

{

   g.drawImage(images[i], 410, 40+i * 100, this);

}

循环绘制出Image的数组对象images中的每一个图像对象。因为,每个图像对象的绘制横坐标都为410像素(磅),而纵坐标依次递增100像素(磅),所以,显示效果呈现纵向排列。如图2.43③、2.43④、2.43⑤所示。

为了测试MediaTrackerApplet.java程序中的异常捕获功能是否正常工作,我们将images子目录下的background.gif,以及logo2.jpg分别重新改名为bf.gif和logo2bak.jpg。重新启动IE,再调用MediaTrackerApplet.html文档,我们可以看到,程序中的异常捕获功能已经能够正常工作了。因为,每个图像对象都定义了惟一的标识,所以在输出结果上,可以看到标志为“0”和“2”的图像对象出现了错误,而这两个图像文件正是我们刚刚更名前的background.gif以及logo2.jpg(标志分别为0和2,见源程序第20、25行)。出现异常后的程序输出结果,如图2.44所示。

0 0
原创粉丝点击