無限ループとrepaintメソッド

広告

アプレットで新規にスレッドを作成し、そのスレッドを開始するとrunメソッドが内部的に呼び出されます。例えば別々の画像を5枚表示したら、それでスレッドを終了させてもいいのであれば下記のように記述します。

public void run(){
  /* 画像1を表示する処理 */
  /* 画像2を表示する処理 */
  /* 画像3を表示する処理 */
  /* 画像4を表示する処理 */
  /* 画像5を表示する処理 */
}

そうではなく、例えばアプレット上でアニメーションを動かし続けたり、ゲームを行ったりするのであれば、スレッドが終了しては困るわけです。runメソッドが終了したらスレッドは終了しますので、runメソッド内で無限ループを作成し、その中で実行したい処理を行います。

public void run(){
  /* 無限ループ作成 */
  while(true){
    /* スレッドで行わせたい処理 */
  }
}

無限ループにしてしまって大丈夫かと思われると思いますが、アプレットが終了するとこのスレッドも終了となりますので気にしなくても大丈夫です。アプレットが終了するとはアプレットが表示されているページから他のページにブラウザが移動した場合やブラウザを終了させた場合です。

repaint処理による再描画

単に無限ループしても何も変わりませんので、アプレット上で表示される内容を変更させる必要があります。アプレットで描画を処理しているpaintメソッドは、アプレットが表示されている部分が隠れたりブラウザが一度最小化したりした後で再度表示が必要になった時には自動的に呼び出されます。ただアプレットでアニメーションを行わせようとすると、その都度ブラウザを小さくしたり何か他のアプリケーションで隠してみたりする事は出来ません。

そこで使われるのがrepaintメソッドです。paintメソッドは内部的に呼び出されるメソッドですので、プログラム内で直接呼び出すことはできません。代わりにrepaintメソッドを呼び出すと、強制的にアプレットの再描画の依頼を出すことが出来ます。その結果としてpaintメソッドが呼び出されることになります。

1. repaintをプログラム内で呼び出す
2. updateメソッドが内部的に呼び出され、画面をクリアした後でpaintメソッド
   を呼び出す。
3. paintメソッドによってアプレットが描画される

ここで重要なのがrepaintメソッドには引数も何も指定することは出来ません。その為、最終的に実行されるpaintメソッドに何か引数を渡すことは出来ず、paintメソッドはメソッド内に書かれていることを毎回実行するだけになります。そこでpaintメソッド内で外部のグローバル変数などを参照して、その変数の値に応じた描画処理をするように記述しておきます。

前のページのサンプルをもう一度見てください。

public class ThreadTest extends Applet implements Runnable{
  Thread thread = null;
  int x, y;
  Color col;

  public void init(){
    x = 10;
    y = 10;
    col = new Color(255, 0 ,0);

    thread = new Thread(this);
    thread.start();
  }

  public void paint(Graphics g){
    g.setColor(col);
    g.drawOval(x, y, 50, 50);
  }

  public void run(){
    while(true){
      x = (int)(Math.random() * 100);
      y = (int)(Math.random() * 100);

      int red = (int)(Math.random() * 255);
      int green = (int)(Math.random() * 255);
      int blue = (int)(Math.random() * 255);
      col = new Color(red, green, blue);

      repaint();
    }
  }
}

前のページのサンプルでは、runメソッド内の無限ループ内で、描画する位置と色を表す変数の値を変更してから、再描画を行うためのrepaintメソッドを呼びだしています。その結果paintメソッドが実行されるのですが、paintメソッドでは外部の変数に設定された位置と色を使って円を描きます。このように、repaintを呼び出す前に必要な設定を行ってからrepaintを呼び出すことで、アプレット上で様々な描画を次々と行う事ができます。

( Written by Tatsuo Ikura )