上一节中,我们用Java显示了一张图片,这一节我们来尝试着用Java来显示一个超简单的动画。
先说点和代码无关的事情。动画的话,其实就是利用了人眼的视觉停留特性。如果眼前的画面以0.1秒的间隔来更换的话,就会给人一种画面在运动的感觉,小时候在书角画小人时利用的也是这一点。
首先,我们需要找一组连续起来的图片,制作过GIF动画图片的朋友应该体会的就更深一点。
代码方面是在第一节的基础上修改制成的,Main和MyFrame这两个类没有做修改。
面板源码:
package simple;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Panel;
import java.awt.image.BufferedImage;
public class MyPanel extends Panel implements Runnable{
private final int width=519;
private final int height=569;
private final Image screenImage = new BufferedImage(width, height, 2);
private final Graphics2D screenGraphic = (Graphics2D) screenImage.getGraphics();
private Image backgroundImage;
private Image[] images;
private int index;
private Thread animator;
public MyPanel() {
loadImage();
// 设定焦点在本窗体
setFocusable(true);
// 设定初始构造时面板大小,这里先采用图片的大小
setPreferredSize(new Dimension(width,height));
// 绘制背景
drawView();
animator=new Thread(this);
start();
}
private void start() {
animator.start();
}
/**
* 载入图像
*/
private void loadImage() {
//因为图片更改了位置,所以换成用工具类来获取图片
backgroundImage = FileUtility.getBackground();
images = FileUtility.getImages("f");
}
private void drawView() {
screenGraphic.drawImage(backgroundImage, 0, 0, null);
}
@Override
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
int animWidth = images[index].getWidth(null);
int animHeight = images[index].getHeight(null);
screenGraphic.drawImage(images[index], (width - animWidth) / 2+5,(height - animHeight) / 2+5, null); //图片选择的不太好,需要微调一下。如果选择了OK的图片就不必+5了
g.drawImage(screenImage, 0, 0, null);
}
public void run() {
Thread me = Thread.currentThread();
while (animator == me) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
synchronized (this) {
index++;
if (index >= images.length) {
index = 0;
}
}
repaint();
}
}
}
新增的工具类源码:
package simple;
import java.awt.Image;
import java.io.File;
import javax.swing.ImageIcon;
public class FileUtility {
/**
* 获得文件夹下*.png文件的个数
*
* @return
*/
public static int getFileCount() {
// 获得真实路径
String userDir = System.getProperty("user.dir");
// 获得文件分隔符(在 UNIX 系统中是"/")
String se = System.getProperty("file.separator");
File file= new File(userDir+se+"image");
if (!file.isDirectory()) {
return 0;
}
String[] fileStr = file.list();
int count = 0;
for (String s : fileStr) {
String tail = s.substring(s.lastIndexOf("."), s.length()); // 小尾巴
if (".png".equalsIgnoreCase(tail)) { //不区分大小写
count++;
}
}
return count;
}
public static Image getBackground() {
String userDir = System.getProperty("user.dir");// 获得真实路径
String se = System.getProperty("file.separator"); // 获得文件分隔符(在 UNIX 系统中是"/")
ImageIcon icon = new ImageIcon(userDir+se+"image"+se+"background.png");
if(icon.getImage().getWidth(null)<0) {
return null; //如果未找到图片则返回空
}
return icon.getImage();
}
/**
* 获得指定人物的动画效果图
*
* @param name
* @return
*/
static Image[] getImages(String name) {
String userDir = System.getProperty("user.dir");// 获得真实路径
String se = System.getProperty("file.separator"); // 获得文件分隔符(在 UNIX 系统中是"/")
Image[] images=new Image[getFileCount()-1]; //减掉的1是背景图片
for(int i=0;i<images.length;i++) {
ImageIcon icon = new ImageIcon(userDir+se+"image"+se+"f"+i+".png");
images[i]=icon.getImage();
}
return images;
}
/** 测试用主方法 */
public static void main(String[] args) {
System.out.println(getFileCount());
}
}
在MyPanel类中引入了线程,每0.1秒从图片数组中取出下一次元素刷新一次画面
总结:这几个类其实写的很粗糙,最多只是抛砖引玉喽。