MediaTrackerによる画像読み込み待ち

広告

今まで記述した来た通り、getImageメソッドで画像ファイルを読み込む場合、画像の読み込みが完了するのを待たず、すぐ次の処理へ進みます。特に問題が無い場合もありますが、画像を使った処理を行う場合に一部画像を読み込みが出来ていない状態で動いてしまうのを避けたい場合もあるはずです。

そのような場合に、MediaTrackerクラスを使うことで画像が読み込み完了するまで監視を行う処理を行います。

  • java.lang.Object
  • java.awt.MediaTracker
  • public class MediaTracker extends Object implements Serializable

MediaTrackerクラスは複数の画像や音声などの読み込みの監視を行う事が出来ます。利用手順は下記のようになります。

まずMediaTrackerクラスのオブジェクトを作成します。コンストラクタは1つだけ用意されており下記となります。

指定されたコンポーネントのイメージを監視するメディアトラッカーを作成しま
す。

パラメータ:
  comp - イメージが最終的に描画されるコンポーネント

引数には画像が描画されるコンポーネントですので、アプレット自身となりますので「this」を指定しておいて下さい。

MediaTracker tracker = new MediaTracker(this);

次に読み込みの監視の対象となる画像を登録します。MediaTrackerクラスのaddImageメソッドを使います。

このメディアトラッカーによって監視されているリストにイメージを追加します。
そのイメージは、最終的にそのデフォルトの (スケーリングされていない) サイ
ズで表されます。

  パラメータ:
    image - 監視されるイメージ
    id - このイメージを監視するために使用する識別子

引数には監視対象のImageオブジェクトと監視対象を識別するためのID番号(任意の整数)を付けます。

MediaTracker tracker = new MediaTracker(this);

Image img1 = getImage(getCodeBase(), "file1.gif");
Image img2 = getImage(getCodeBase(), "file2.gif");
Image img3 = getImage(getCodeBase(), "file3.gif");

tracker.addImage(img1, 0);
tracker.addImage(img2, 1);
tracker.addImage(img3, 2);

次に実際に画像の読み込みを行います。画像は実際に描画が行われるまで読み込みを開始しません。つまりdrawImageなどが行われるまでは、実際には読み込みを行わないのです。その為、MediaTrackerでは画像を事前に読み込み開始するためのメソッドが用意されています。

このメディアトラッカーによって監視される、指定された識別子を持つすべての
イメージのロードを開始します。このメソッドは、指定された識別子を持つすべ
てのイメージがロードを完了するまで待機します。

イメージのロードまたはスケーリング中にエラーが発生すると、そのイメージの
ロードは完了したと見なされます。isErrorAny と isErrorID メソッドを使うと、
エラーを調べられます。

パラメータ:
  id - 調べる対象となるイメージの識別子 
例外: 
  InterruptedException - 別のスレッドがこのスレッドに割り込んだ場合

引数に指定したID番号を持つ監視対象の読み込みを開始します。例外が発生する可能性があるので注意して下さい。また識別ID番号を指定して読み込みを行うのではなく、全ての監視対象の読み込みを開始するにはwaitForAllメソッドを使います。

このメディアトラッカーによって監視されているすべてのイメージのロードを開
始します。このメソッドは、監視中のすべてのイメージのロードが完了するまで
待機します。

イメージのロードまたはスケーリング中にエラーが発生すると、そのイメージの
ロードは完了したと見なされます。isErrorAny または isErrorID メソッドを使
うと、エラーを調べられます。

例外: 
  InterruptedException - 別のスレッドがこのスレッドに割り込んだ場合

実際に使う場合には下記のようになります。

MediaTracker tracker = new MediaTracker(this);

Image img1 = getImage(getCodeBase(), "file1.gif");
Image img2 = getImage(getCodeBase(), "file2.gif");
Image img3 = getImage(getCodeBase(), "file3.gif");

tracker.addImage(img1, 0);
tracker.addImage(img2, 1);
tracker.addImage(img3, 2);

try {
  tracker.waitForAll();
} catch (InterruptedException e) {
}

以上で画像の事前読み込み処理は完了となります。

サンプルプログラム

では実際に試してみましょう。下記では大きい画像ファイルを3枚読み込んで縮小して表示させます。まずMediaTrackerを使わない場合を見てみます。

ImageTest5.java

import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;

/*
<applet code="ImageTest5.class" codebase="class" width="150" height="150">
</applet>
*/

public class ImageTest5 extends Applet{
  Image img1;
  Image img2;
  Image img3;

  public void init(){
    img1 = getImage(getCodeBase(), "../img/hana01.png");
    img2 = getImage(getCodeBase(), "../img/hana02.png");
    img3 = getImage(getCodeBase(), "../img/hana03.png");
  }

  public void paint(Graphics g){
    g.drawImage(img1, 0, 0, 48, 36, this);
    g.drawImage(img2, 60, 0, 48, 36, this);
    g.drawImage(img3, 0, 48, 48, 36, this);
  }
}

下記で実際に試す事が出来ます。こちらの場合は読み込みが終わった画像から順に表示が行われます。

ImageTest5.html

サンプルプログラム

次にMediaTrackerを使った場合を見てみます。

ImageTest6.java

import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;

/*
<applet code="ImageTest6.class" codebase="class" width="150" height="150">
</applet>
*/

public class ImageTest6 extends Applet{
  Image img1;
  Image img2;
  Image img3;
  MediaTracker tracker;

  public void init(){
    tracker = new MediaTracker(this);

    img1 = getImage(getCodeBase(), "../img/hana01.png");
    img2 = getImage(getCodeBase(), "../img/hana02.png");
    img3 = getImage(getCodeBase(), "../img/hana03.png");

    tracker.addImage(img1, 0);
    tracker.addImage(img2, 1);
    tracker.addImage(img3, 2);
  }

  public void start(){
    try {
      tracker.waitForAll();
    } catch (InterruptedException e) {
    }
  }

  public void paint(Graphics g){
    g.drawImage(img1, 0, 0, 48, 36, this);
    g.drawImage(img2, 60, 0, 48, 36, this);
    g.drawImage(img3, 0, 48, 48, 36, this);
  }
}

下記で実際に試す事が出来ます。こちらの場合は全ての画像が読み込まれた時点でまとめて表示が行われます。

ImageTest6.html

違いが分かりますでしょうか。

ちなみに実際にブラウザで見てみると下記のようになります。

( Written by Tatsuo Ikura )