補足4 Applet に改造し、Web で実行してみよう!

MIDlet を Applet に改造しよう

Palm で動作する Java アプリケーションは、MIDlet というクラスを継承しなければなりません。 それと同様に、Web ブラウザで動作するアプリケーションは、 Applet というクラスを継承しなければなりません。

MIDlet は Applet の簡易版のような感じなので、 MIDlet から Applet への改造は意外に簡単だったりします。 第4回 で作成した迷路ゲームで試してみましょう!

まずは迷路データを改造

MazeData と MazeData2 は、特に J2ME に依存したデザインではありません。 なのでそのまま利用することができます。 驚いたことに、コンパイル済みのバイナリ (.class ファイル) を、 そのまま利用可能だったりします。

まずは適当な作業ディレクトリを作りましょう。 私は c:\mywork にしました。 そして c:\j2mewtk\apps\MazeGame\classes から MazeData.class と MazeData2.class をコピーします。

次に c:\j2mewtk\apps\MazeGame\src から、 ソースファイル MazeData3.java をコピーします。 そして MazeData3.java の内容を修正します。

MazeData3.java (Applet用)
import java.awt.*;

public class MazeData3 extends MazeData2 {
  public Graphics maze_g;
  public int maze_x, maze_y;
  public int maze_width, maze_height;
  public int block_width, block_height;


  // 最初に迷路を描画する際に呼び出される
  public void drawMaze(Graphics g, int x, int y, int w, int h) {
    // 迷路の描画情報を保存
    maze_g = g;
    maze_x = x;
    maze_y = y;
    maze_width = w;
    maze_height = h;

    // ブロックのサイズを求める
    block_width = w / width;
    block_height = h / height;

    // 実際に迷路を描画する
    updateMaze();
  }

  public void updateMaze() {
    // まず描画する範囲を白色で塗りつぶす
    // 描画する範囲は、ブロックの大きさの整数倍に切り捨て
    // (単に w, h を使うと、右端と下端に隙間ができてしまう)
    maze_g.setColor(new Color(0x00ffffff));
    maze_g.fillRect(maze_x, maze_y, block_width * width, block_height * height);

    // 迷路データをチェックし、1ブロックずつ描画
    maze_g.setColor(new Color(0x00000000));
    for (int loop = 0; loop < data.length; loop++)
      drawBlock(maze_g, data[loop], maze_x + loop % width * block_width,
            maze_y + loop / width * block_height, block_width, block_height);
  }

  public static void drawBlock(Graphics g, byte type, int x, int y, int w, int h) {
    if (type == WALL)
      g.fillRect(x, y, w, h); // 描画色は黒であることが前提
    else if (type == ENTRANCE) {
      g.setColor(new Color(0x00ff0000));
      g.drawArc(x, y, w, h, 0, 360);
      g.setColor(new Color(0x00000000));
    } else if (type == EXIT) {
      g.setColor(new Color(0x000000ff));
      g.fillArc(x, y, w, h, 0, 360);
      g.setColor(new Color(0x00000000));
    }
  }
}

まずは最初の行の "import javax.microedition.lcdui.*;" を "import java.awt.*;" に変更します。 これは MIDlet と Applet では、使用する機能 (API) の種類が違うからです。

そして6ヶ所ある "g.setColor(0x00000000);" という色を設定する部分を、 "g.setColor(new Color(0x00000000));" という風に変更します。 MIDlet の setColor は int型 での指定ができましたが、 Applet では色を定義した専用クラス Color があるので、使用しなければなりません。

後は javac コマンドで、MazeData3.java ソースファイルをコンパイルし、 MazeData3.class ファイルを生成すれば終了です。

C:\mywork>javac MazeData3.java

C:\mywork>

最初の import 文と、色の設定部分だけの変更で、 MIDlet用のクラス から Applet用のクラス への変更が終了したことになります。

実は import した java.awt は Applet 専用ではなく、、 Java (J2SE) で一般的に使用されている基本的なグラフィック描画機能です。 つまりこの MazeData3 は、Applet だけではなく、 J2SE を用いた開発すべてに利用できる部品になりました。 ラッキー(?)ですね。

そして表示部分を改造

まずは c:\j2mewtk\apps\MazeGame\src から、 ソースファイル SampleMaze2.java をコピーします。 そして SampleMaze2.java の内容を修正します。

SampleMaze2.java (Applet版)
import java.util.*;
import java.applet.*;
import java.awt.*;

public class SampleMaze2 extends Applet {
  private MazeData3 md;

  public void start() {

    // 迷路データを定義する
    md = new MazeData3();
    md.width = 10;  // 迷路の横方向の大きさ (小さ目の値に変更)
    md.height = 12; // 迷路の縦方向の大きさ (小さ目の値に変更)
    md.init(new Date().hashCode());  // 迷路の自動生成

    Canvas canvas = new Canvas() {
      public void paint(Graphics g) {
        g.setColor(new Color(0x00000000));
        g.fillRect(0, 0, getWidth(), getHeight());
        md.drawMaze(g, 5, 5, getWidth() - 10, getHeight() - 10);
      }
    };

    setLayout(new BorderLayout());
    add(canvas);
  }
}

青字 の部分は MazeData3 と同じなので説明は省きます。

MIDlet ではなくて Applet なので、 "import javax.microedition.midlet.MIDlet;" が "import java.applet.*;" になります。 また "extends MIDlet" も "extends Applet" になります。

MIDlet では "startApp()" だったメソッドは、 Applet では "start()" という名前になります。 ちなみに MIDlet のほうが新しい規格なので、「"start" では一般的過ぎて不明瞭」 とかいう理由で、変更されたのではないかと推察します。

また MIDlet では startApp(), pauseApp(), destroyApp() は継承する際に定義する必要がありました。 しかし Applet ではこのような制限はありませんので、 "start()" だけを定義しています。 昔はよりアバウトだった、でしょうかね。

Color と同様、Applet (J2SE) の部品には レイアウト という MIDlet に無い概念があります。 setLayout(new BorderLayout()); として標準的なレイアウト BorderLayout を指定しておきます。

最も大きな違いは、 "Display.getDisplay(this).setCurrent(canvas);" の部分がシンプルに add(canvas); と変更されている部分だと思います。 MIDlet が最低限の機能を提供していないのと違って、 Applet は HelloWorld で使用した "Form" のような機能を含んでいます。 つまり、その上に部品を載せることができる。 だから単純に、Canvas を add すれば表示できてしまうんですね。

どうでしょう? 小さなサンプルなので 「修正個所が多い」 ように感じられてしまうかもしれませんが、 細かい記述の修正が多く、プログラムの本体 (アルゴリズム) は、ほとんどそのまま流用できている点がポイントです。 start() の中身は、 Color クラスを追加しただけで済んでいますよね。

さて javac コマンドで、SampleMaze2.java ソースファイルをコンパイルし、 SampleMaze2.class ファイルを生成しましょう。

C:\mywork>javac SampleMaze2.java

C:\mywork>

いま、c:\mywork ディレクトリには、以下の7つのファイルが存在しているハズです。

  • MazeData.class
  • MazeData2.class
  • MazeData3.java
  • MazeData3.class
  • SampleMaze2.java
  • SampleMaze2.class
  • SampleMaze2$1.class
最後の "SampleMaze2$1.class" ってのは、無名クラスを使用すると生成されるものです。 第3回 のおまけコラムに説明があります。 実行に必要ですのでお忘れなく。 逆に .java ファイルは実行には必要ありません。

まずは AppletViewer での実行が基本

.class ファイルだけあっても、Web ブラウザーでの実行はできません。 Applet を起動するための HTML ファイルが必要です。 SampleMaze2.html という名前のテキストファイルを新規作成し、以下のように入力してください。

SampleMaze2.html
<html><body>
<h2>SampleMaze2 demo</h2>
<applet code="SampleMaze2.class" width="320" height="320">
</applet>
</body></html>

Applet のテストをする appletviewer というツールがありますので、 これで SampleMaze2 を動かしてみましょう。 ちなみに迷路の大きさは 10x12 に変更してあります。

C:\mywork>appletviewer SampleMaze2.html

C:\mywork>

SampleMaze2 on AppletViewer

Web ブラウザーで実行してみましょう

さていよいよ、Web ブラウザーで実行してみましょう。 JDK や J2ME Toolkit をインストールしてなくても、POSE が動かなくも、 Palm実機を持っていなくても、この講座を読んでいる方、全てが実行できますので是非。

ここをクリックです! --> 実行

リロードすると、新しい迷路が表示されるのも確認してみてください。

うまく実行できましたか? 1.3.1 以上の Java Plug-in が入っていないとうまく実行できないので、 SUN の Clockデモ でも実行してみてください。 Java Plug-in が有効でなければ、自動的にダウンロードが始まるはずです。

楽しんでいただけましたか?

Palm だけじゃなくて、携帯電話や Web ブラウザまで。 いろいろ広がる Java の世界の一端を、感じ取っていただけたら幸いです。

幅広く、楽しみましょう。 (^-^)/


Copyright (c) 2002 Toshio Yamashita
first version 2002/08/21