ダブルバッファリング


イメージの生成

さて、ここでダブルバッファリングの基本的概念と扱いに触れましょう
ダブルバッファリングとは、早い話が画像更新のちらつきを回避する技術だと思ってください

以前、コンポーネントを更新しつづけることで簡単なアニメーションを表現しました
しかし、そのときは更新するたびに画面がちらついていましたね
これでは自分のWebページがピカチ○ウ現象に陥りかねません

画面がちらつくのは、コンポーネント更新時に一度背景色で塗りつぶすためです
この現象はupdate()メソッドをオーバーライドすることで回避できますが、まだ問題があります
画面に何かを付け足していくようなプログラムの場合は、これで解決することができますが
画面の一部を動的に更新する場合、この方法だけでは実現できません

そこでダブルバッファリングが用いられます
ダブルバッファリングの基本概念は、イメージの生成です

まずオフスクリーンと呼ばれる、見えないウィンドウを作ります
プログラムはこの見えないウィンドウを更新します
最後に、オフスクリーンをコンポーネントにdrawImage()で描画することで
画面のクリアからイメージ操作の全ての過程をウィンドウに映すことなく
全ての作業を終えてから表示することで、ちらつきを防止することができるのです

まず、オフスクリーンとなるバッファを生成します
これはComponentクラスのcreateImage()メソッドを使用します

public Image createImage( ImageProducer producer )
public Image createImage( int width, int height )

ImageProducerを渡すcreateImageはダブルバッファリングでは用いません
今回使用するのは下のcreateImageの書式です

widthとheightはオフスクリーンとなるバッファのサイズを指定します
ただし、このオフスクリーンを操作するにはグラフィックコンテキストが必要です
drawRect()やfillOval()など、グラフィックを担当するのはGraphicsクラスでしたね
グラフィックコンテキストを得るにはImageクラスのgetGraphics()メソッドを使用します

public abstract Graphics getGraphics()

オフスクリーン イメージに描画するためのグラフィックス コンテキストを作成します
getGraphics()が返したコンテキストが操作の対象になります
全ての作業はバッファで行われ、最後にバッファをウィンドウにコピーします
import java.applet.Applet;
import java.awt.*;

/*	<applet code="App21.class" width="600"height="300">
 	</applet>
*/

public class App21 extends Applet {
	Image buf;
	Graphics ct;
	Dimension dim;

	public void init() {
		dim = getSize();
		buf = createImage(dim.width , dim.height);
	}

	public void paint(Graphics g) {
		ct = buf.getGraphics();
		ct.setColor(Color.white);
		ct.fillRect(0 , 0 , dim.width , dim.height);
		ct.setColor(Color.red);
		ct.fillRect((dim.width / 2) - 50 , (dim.height / 2) - 50 , 100 , 100);

		g.drawImage(buf , 0 , 0 ,this);
	}
}
アプレット

このプログラムは動的にアニメーションしないので、あまり意味は感じませんが
内部動作は普段と大きく違います

まず buf = createImage(dim.width , dim.height); で
bufにダブルバッファリングで使用できる、オフスクリーンで描画可能なイメージを作成します
次に、生成されたイメージ(オフスクリーン)のグラフィカルコンテキストを ct = buf.getGraphics(); で生成します
ここで生成したグラフィカルコンテキストを操作することで、オフスクリーンのイメージを描画できます

最後に g.drawImage(buf , 0 , 0 ,this); でイメージをコンポーネントにコピーしています
これがダブルバッファリングです

この技法を用いれば、アニメーションで画面がちらつくことがありません
Javaアプレットでゲームなどを作る時は、重要な画面操作の一つです
import java.applet.Applet;
import java.awt.*;

/*	<applet code="App22.class" width="300"height="300">
 	</applet>
*/

public class App22 extends Applet implements Runnable {
	boolean chkx = true , chky = true;
	int x = 250 , y = 140;
	Thread th;
	Image buf;
	Graphics ct;
	Dimension dim;

	public void init() {
		th = new Thread(this);
		th.start();

		dim = getSize();
		buf = createImage(dim.width , dim.height);
	}

	public void run() {
		try {
			while(true) {
				if (chkx) x++;
				else x--;
				if (chky) y++;
				else y--;

				if (x == (dim.width - 20)) chkx = false;
				if (x == 0) chkx = true;
				if (y == (dim.height - 20)) chky = false;
				if (y == 0) chky = true;

				repaint();
				Thread.sleep(10);
			}
		}
		catch (InterruptedException err) { }
	}

	public void update(Graphics g) {
		paint(g);
	}
	public void paint(Graphics g) {
		if (ct == null) ct = buf.getGraphics();
		ct.setColor(Color.white);
		ct.fillRect(0 , 0 , dim.width , dim.height);
		ct.setColor(Color.red);
		ct.fillRect(x , y , 20 , 20);

		g.drawImage(buf , 0 , 0 ,this);
	}
}
アプレット

一見プログラムは長ったらしいですが
それは、宣言部や制御部分(アルゴリズム)であり、バッファリングの重要な部分は極一部です
このプログラムはまだ汎用的とは言えませんが、改良すれば面白いものが作れるかもしれません

アプレットやアプリケーションの開発にアニメーションは欠かせません
アニメーションはソフトウェアの演出やレイアウトに大きく影響します



前のページへ戻る次のページへ