Imageの読み込みと描画のタイミング

イメージの表示を行うには、 Graphicsクラスのメソッド drawImage() を利用します。 最初の引数は表示したい Imageのオブジェクト、 続く2つの引数はイメージのアプレット内の座標です。

Graphics g;  Image image;
g.drawImage( image, 0, 0, this );  

イメージのサイズを調べるためのメソッド getWidth(),getHeight() を使います。 これらは Imageクラスのメソッドです。 また、drawImage()メソッドの第4、5引数に int型の数値を与えると、 それらは表示されるイメージのサイズと解釈されます。 (イメージは「切り取られる」のではなく、自動的に伸縮します。) たとえば次の例は、イメージを縦横に2倍に拡大して表示します。

Graphics g;  Image image;
int w = image.getWidth( this );
int h = image.getHeight( this );
g.drawImage( image, 0, 0, w*2, h*2, this );  

ところで、getWidth(),getHeight(),drawImage()の各メソッドで 引数に指定している this は何を意味しているのでしょうか? this は特別なキーワードで、そのクラス自身を表します。 つまりイメージを呼び出したアプレット自身です。 this が引数で渡される理由は、 イメージの読み込み処理が独立したスレッドによって 処理されること関係があります。 一般に、インターネットを通じてイメージデータを読み込むには 時間がかかります。 その待ち時間に別の処理を行った方が効率がいいのですが、 処理の順番に混乱が生じないように工夫が必要になります。
イメージの読み込みとイメージの表示の処理がうまく同期をとるため、 Appletクラスにはイメージからのメッセージを受け取る ImageObserver という機能が 実装されています。 イメージのデータがある程度読み込まれるたびに、 アプレットはその通知を受け取り、 再表示のため update()メソッドを自動的に呼び出せる仕組みになっています。 (アプレットの使用するイメージが、 処理を行いながら少しずつ表示されるのは、この機構のおかげです。)

もう一つの注意点があります。 イメージデータの読み込みは、描画命令が最低一回呼び出された段階で始まる のです(!)。 これは逆説的に思えるでしょうが、不必要な読み込みを行って無駄な通信を 行わないための工夫です。(つまり、描かれることがないデータは 決して読み込まない。) また、起動時に余計な時間がかかることを防ぐ意味もあります。 init()メソッドの中で全部のイメージを getImage() で得る形式で 書いたとしても、実際にはそれよりも先に paint()メソッドが呼び出されるわけです。
通常は paint()メソッドがアプレット起動の直後に呼び出されるため、 その中で描画が実行されるイメージは自動的に読み込みが始まります。 しかし、プログラムの実行の途中で初めて描画が必要になるような ケースでは、どこかでダミーの描画を実行しておかないと イメージの生成が行われないこともあるので注意してください。