[pre]
//程序名animatorcanvas.java , 项目animator
//用线程实现动画
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class animatorcanvas extends canvas implements runnable {
image[] frames;
int left, top;
boolean alive;
int interval;
int currentframe;
int numframes;
midlet midlet;
thread thread;
public animatorcanvas(midlet midlet, image[] frames, int left, int top, int interval) {
this.frames = frames;
this.left = left;
this.top = top;
this.interval = interval;
this.alive = true;
this.currentframe = 0;
this.numframes = frames.length;
this.midlet = midlet;
thread= new thread(this);
thread.start();
}
public animatorcanvas(midlet midlet, image[] frames, int interval) {
this(midlet, frames, 0, 0, interval );
this.left = ( this.getwidth() - frames[0].getwidth() ) / 2;
this.top = ( this.getheight() - frames[0].getheight() ) / 2;
}
public void paint(graphics g) {
g.setcolor(0x00000000);
g.fillrect(0,0,getwidth(),getheight());
g.drawimage(frames[currentframe++], left, top, graphics.left graphics.top);
if (currentframe >= numframes) {
currentframe = 0;
}
}
public void keypressed(int keycode) {
if (getgameaction(keycode) == fire) {
alive = !alive;
} else {
thread = null;
((animator)midlet).exit();
}
}
public void run() {
while(true) {
if (alive) {
repaint();
try {
thread.sleep(interval);
} catch (interruptedexception e) {
}
}
}
}
}
[/pre]
在run方法的while循环中,使用alive参数对它的行为进行控制。在midlet主类中生成这个canvas类的实例,并设置为当前屏幕即可,比如下面的代码:
[pre]
//程序名animator.java , 项目animator
//用线程实现动画
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class animator extends midlet {
protected void startapp() {
try {
image[] images = new image[] {
image.createimage("/duke2.png"),
image.createimage("/duke1.png"),
image.createimage("/duke3.png"),
image.createimage("/duke1.png")
};
display.getdisplay(this).setcurrent(new animatorcanvas(this,images,100));
} catch (java.io.ioexception e) {
}
}
public void exit(){
destroyapp(true);
notifydestroyed();
}
protected void destroyapp( boolean unconditional ){}
protected void pauseapp() {}
}
[/pre]
callserially方法
前面的例子使用一个while循环语句,反复调用repaint()方法,容易造成的问题就是可能与其他线程发生冲突。display类提供了一个事件序列化的方法callserially,使runnable对象在一个重画周期完整后立即调用它的run()方法,利用这种特性取代run方法中的循环语句,把上一小节animatorcanvas类的run方法更改如下:
[pre]
//程序名animatorcanvas.java , 项目animator
public void run() {
//while(true) {
if (alive) {
repaint();
try {
thread.sleep(interval);
} catch (interruptedexception e) {
}
}
display.getdisplay(midlet).callserially(this); //增加的代码
//}
}
[/pre]
然后重新编译并运行这个程序,其效果与11.1.2小节中例子类似。实际上这也是一个循环,相当于在run方法中调用了run方法(本身)。这里把callserially调用放在if语句之外,这样使用按键事件停止动画时,线程仍在运行(循环调用run方法)。如果放在if语句之内,则当从if语句跳出(alive == false)时,循环也会结束,线程也随之结束(重新设置alive == true时也不会启动线程)。因此使用run方法时应该注意,避免造成意外情况。
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器