Nanashi-softプログラマ専用iアプリ


◇iアプリ(DoJa)-メインループ-

処理のメインループを作成します
色々な方法があるので,これはその中の1つの方法だと思って下さい

○Canvasクラス定義

画面上にイメージを表示する為には,Canvasクラスを使用する必要があります
メインクラスとは別に,Canvasクラスを継承したクラスを定義します

class test1Canvas extends Canvas{
}

これをビルドすると

C:\iDKDoJa4.1\apps\test1\src\test1.java:24: class test1Canvas のスーパークラス Canvas が見つかりません。

と怒られます
なぜなら importでライブラリを指定していないからです

デフォルトでは,
import com.nttdocomo.ui.IApplication;
と,なぜか1ファイルだけがピンポイントで指定されていますので,これを
import com.nttdocomo.ui.*;
に書き替えて下さい

そうすると,

C:\iDKDoJa4.1\apps\test1\src\test1.java:24: class test1Canvas は abstract クラスでなければなりません。このクラスでは、class com.nttdocomo.ui.Canvas から派生する void paint(com.nttdocomo.ui.Graphics) を定義していません。

に怒られ方が変わります
これは paintメソッドを必ず定義しなければならない事を示していますので,書き足します

class test1Canvas extends Canvas{
  public void paint(Graphics g){
  }
}

これでビルドが通るようになりました

○メインループ作成

作成した Canvasクラス内にメインループを作成します
なぜココに作るのかと言うと,paintメソッドと同じクラスの方が都合が良いからです

class test1Canvas extends Canvas{
  public void mainloop(){
    while(true){
      try {
        Thread.sleep(1);
      }catch(Exception e){}
    }
  }

  public void paint(Graphics g){
  }
}

mainloopメソッドを定義して,while文で無限ループを作成します
負荷が異常に上がるとアプリが停止する端末がいるので,スリープしてシステムに制御を戻します

これをメインクラスから呼び出します

public class test1 extends IApplication {
  public void start() {
    test1Canvas c=new test1Canvas();
    Display.setCurrent(c);
    c.mainloop();
  }
}

Canvasクラスを生成して,
描画をメインクラスから Canvasクラスに移し,
mainloopを呼び出しています

○何か表示してみる

これだけだと,本当にループが作成できているのかわかりません
そこで,連番を表示してみます

class test1Canvas extends Canvas{
  //変数宣言
  int i=0;

  public void mainloop(){
    while(true){
      //カウントアップ
      i++;

      //再描画
      repaint();

      try {
        Thread.sleep(1);
      }catch(Exception e){}
    }
  }

  public void paint(Graphics g){
    //画面クリア
    g.setColor(Graphics.getColorOfName(Graphics.WHITE));
    g.fillRect(0, 0, 240, 240);

    //連番表示
    g.setColor(Graphics.getColorOfName(Graphics.BLACK));
    g.drawString(Integer.toString(i), 0, 20);
  }
}

変数 iをメソッドまたいで使用するので,クラスの先頭に宣言
メインループ内でカウントアップしながら,再描画 reapintメソッド呼出す

paintメソッド内で,画面を白で塗りつぶしてクリア
int型を String型に変換しつつ,drawStringで描画

○ちゃんと描画する

実はこのままでは大きな問題があります
repaintメソッドは機種によって実行方法が異なります
通常はスレッド実行されますので,確実に1ずつカウントアップ表示されません

想像図)
メインスレッド    
   
repaint() repaintスレッド生成
 
カウントアップ   paint()
  ↓処理中
repaint() →×既にrepaintメソッドが生成されているので無視
  処理完了でスレッド破棄
カウントアップ    
   
repaint() repaintスレッド生成

簡単な回避方法として,paintメソッドがきちんと終了した事を確認してから次に移るようにすれば良い

class test1Canvas extends Canvas{
  int i=0;
  //再描画フラグ定義
  boolean paFlg=false;

  public void mainloop(){
    while(true){
      i++;
      //再描画フラグを立てる
      paFlg = true;

      repaint();

      //再描画フラグが立っている間待機
      while (paFlg){
        try {
          Thread.sleep(1);
        }catch(Exception e){}
      }

      try {
        Thread.sleep(1);
      }catch(Exception e){}
    }
  }

  public void paint(Graphics g){
    //画面クリア
    g.setColor(Graphics.getColorOfName(Graphics.WHITE));
    g.fillRect(0, 0, 240, 240);

    //連番表示
    g.setColor(Graphics.getColorOfName(Graphics.BLACK));
    g.drawString(Integer.toString(i), 0, 20);

    //描画終了時に,再描画フラグを落とす
    paFlg = false;
  }
}

描画フラグ paFlgを定義
repaint前にフラグを立てて,それが立っている間ループ
paintの描画が完了した時点でフラグを落とす


TOPプログラマ専用iアプリ