37. アニメーションアプリ

アニメーションアプリ

画像のコマ送りをタイマーで作成してみましょう。コマ画像は6つ程用意しておきます。今回の例では「school-インデックス番号.jpg」としました。

ファイル構成

Timer/
└── images
    ├── school-1.jpg
    ├── school-2.jpg
    ├── school-3.jpg
    ├── school-4.jpg
    ├── school-5.jpg
    └── school-6.jpg
└── src/
    └── school/
        ├── Window.java
        ├── AnimationTask.java
        └── App.java

ウィンドウ作成

JFrameを継承したWindowクラスを作成します。また、駒画像に必要なフィールドを用意します。

Window.java
package school;

import java.util.Timer;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Window extends JFrame {

	public JLabel label;
	public int imageCount = 6;
	public ImageIcon[] images = new ImageIcon[imageCount];
	public int index = 0;
	final String IMAGE_PREFIX = "school-";
	final String IMAGE_EXT = ".jpg"
}

画像初期化処理

画像を配列 imagesに設定します。

Window.java
	public void loadImages() {
		for (int i = 0; i < images.length; i++) {
            String path = "./images/" + IMAGE_PREFIX + (i + 1) + IMAGE_EXT;
			images[i] = new ImageIcon(path);
		}
	}

フレーム作成

JFrameのフレームにラベルを追加します。

Window.java
	public void createWindow() {
		setBounds(0, 0, 1000, 1000);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		label = new JLabel();
		add(label);
		setVisible(true);
	}

コンストラクタ追加

フィールドの選択はすべて解除し、コンストラクタを生成します。

コンストラクタを生成したら、画像初期化とフレーム作成を実行します。

Window.java
	public Window() {
		super();
		
		loadImages();
		createWindow();
	}

画像読み込み処理

ラベルに指定したインデックスで画像を読み込み、インクリメントします。最後の画像になったらインデックスを「0」に戻します。

Window.java
	public void animate() {
		label.setIcon(images[index]);	
		index++;
		//最後の画像だったらインデックス0
		if (index >= images.length) index = 0;
	}

タスク作成

AnimationTaskクラス作成

AnimationTask.javaを作成し、TimerTaskクラスを継承します。

AnimationTask.java
package school;

public class AnimationTask extends TimerTask {

}

フィールド追加

コンストラクタでWindowオブジェクトを受け取るよう、フィールドを追加します。

AnimationTask.java
public class AnimationTask extends TimerTask {
	public Window window;

    ....
}

コンストラクタ追加

「ソース」メニューから「フィールドを使用してコンストラクタの生成...」を選択して、コンストラクタを作成します。

「window」フィールドを選択した状態で、コンストラクタを生成します。

コンストラクタが生成されました。

public class AnimationTask extends TimerTask {
    ...
	public AnimationTask(Window window) {
		super();
		this.window = window;
	}
    ...
}

run() メソッドの実装

コンパイルエラーになるので、エラー部分をマウスオーバーして 【実装されていないメソッドの追加】でrun() メソッドを実装 します。

AnimationTask.java
public class AnimationTask extends TimerTask {

	@Override
	public void run() {
		window.animate();
	}

}

タイマー処理

Windowsクラスにタイマー処理を作成します。

Window.java
	public void startTimer() {
		Timer timer = new Timer(true);
		timer.schedule(new AnimationTask(this), 0, time);
	}

メイン処理

App.javaのメインメソッドで、Windowインスタンスを実行して確認してみましょう。

App.java
public class App {

	public static void main(String[] args) {
		Window window = new Window();
		window.startTimer();
	}

}
結果

ソース

App.java
package school;

public class App {

	public static void main(String[] args) {
		Window window = new Window();
		window.startTimer();
	}

}
Window.java
package school;

import java.util.Timer;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Window extends JFrame {

	public JLabel label;
	public int imageCount = 6;
	public ImageIcon[] images = new ImageIcon[imageCount];
	public int index = 0;
	public long time = 500;
	final String IMAGE_PREFIX = "school-";
	final String IMAGE_EXT = ".jpg";

	public Window() {
		super();
		
		loadImages();
		createWindow();
	}
	
	public void loadImages() {
		for (int i = 0; i < images.length; i++) {
            String path = "./images/" + IMAGE_PREFIX + (i + 1) + IMAGE_EXT;
			images[i] = new ImageIcon(path);
		}
	}

	public void createWindow() {
		setBounds(0, 0, 1000, 1000);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		label = new JLabel();
		add(label);
		setVisible(true);
	}
	
	public void startTimer() {
		Timer timer = new Timer(true);
		timer.schedule(new AnimationTask(this), 0, time);
	}
	
	public void animate() {
		label.setIcon(images[index]);	
		index++;
		if (index >= images.length) index = 0;
	}
}

AnimationTask.java
package school;

import java.util.TimerTask;

public class AnimationTask extends TimerTask {
	
	public Window window;
	
	public AnimationTask(Window window) {
		super();
		this.window = window;
	}

	@Override
	public void run() {
		window.animation();
	}

}