アプレットプログラミング


Javaの特徴である,WWWブラウザの中で動くアプレット(Applet)と呼ばれる プログラムも,通常のGUIプログラムとそれほど差はなく書ける.注意するの は以下の点である. 先ほどのプログラムを書き直してみる.
// <applet code=AppTest width=600 height=450></applet>
  // アプレットを使うため
import java.applet.*;
  // AWTを使うため,
import java.awt.*;
  // イベント駆動関係のクラスを用いるため
import java.awt.event.*;
  // Vectorクラスを用いるため
import java.util.*;

  // 線分のクラスを定義する.
class Line{
  // 始点,終点のX座標,Y座標を int で保持する.
  public int start_x,start_y,end_x,end_y;
  // Lineのコンストラクタ
  public Line(int x1,int x2,int x3,int x4){
   start_x=x1;
   start_y=x2;
   end_x=x3;
   end_y=x4;
  }
}
// 外側のFrameに直接 paintするのではなく, お絵書き領域を作る.
class MyCanvas extends Canvas implements KeyListener, MouseListener, MouseMotionListener{
   // Lineの配列を保持するVectorクラスの変数 lineArrayの宣言
  Vector lineArray;
   // マウスをドラッグ中かどうかを示す boolean型(真偽値)の変数draggingの宣言
  boolean dragging;
   // 表示する色を保持する変数
  Color lineColor;
   // コンストラクタの宣言
  public MyCanvas(){
    super();
    lineArray=new Vector();
     // ドラッグ中ではない
    dragging=false;
     // 線の色は黒に
    lineColor=Color.black;
      // GUI部品と,Event Listenerを関連づける
    setSize(600,400);
    addKeyListener(this);
    addMouseListener(this);
    addMouseMotionListener(this);
  }
  Image offScreenImage;
  Graphics offScreenGraphics;
  public void update(Graphics g){
    if(offScreenImage==null){
      offScreenImage=createImage(600,400); // オフスクリーンイメージを600x400のサイズで作成
      offScreenGraphics=offScreenImage.getGraphics(); // オフスクリーンイメージに描画するための Graphics オブジェクト
    }
    paint(offScreenGraphics); // 次の画面のイメージを作る.
    g.drawImage(offScreenImage,0,0,this); // イメージを本物のスクリーンに書き込む
  }
   // offScreenImageの書き直しをする際に呼ばれる
  public void paint(Graphics g){
    int i;
      // 白で(0,0)-(600,400)を塗り潰す
    g.setColor(Color.white);
    g.fillRect(0,0,600,400);
      // 色を設定
    g.setColor(lineColor);
    int size=lineArray.size();
    if(dragging) size--;
    for(i=0;i< size;i++){
      Line l=(Line)lineArray.elementAt(i);
      g.drawLine(l.start_x,l.start_y,l.end_x,l.end_y);
    }
     // マウスをドラッグ中の時は
    if(dragging){
       // 赤い色で
      g.setColor(Color.red);
       // lines[lineCount] を描画する.
      Line l=(Line)lineArray.elementAt(i);
      g.drawLine(l.start_x,l.start_y,l.end_x,l.end_y);
    }
  }
   // KeyListenerを実装するためのメソッド
  public void keyPressed(KeyEvent e){
     // イベントからキーのコードを取り出す
    int key=e.getKeyChar();
     // デバッグ用の表示
    System.out.println("keyPressed("+e+","+key+")");
     // 入力が 'q'の時は終了する
    if(key=='q') System.exit(0);
  }
   // 要らないイベントに対応するメソッドも中身は空で書いておく必要がある.
  public void keyReleased(KeyEvent e){}
  public void keyTyped(KeyEvent e){}
   // MouseListenerを実装するためのメソッド
  public void mousePressed(MouseEvent e){
     // 押された時のマウスカーソルの位置を得る
    int mx=e.getX(),my=e.getY();
     // デバッグ用の表示
    System.out.println("mousePressed("+e+","+mx+","+my+")");
     // 配列linesのlineCount番目に線分を登録
    lineArray.addElement(new Line(mx,my,mx,my));
     // ドラッグ中であることを示す
    dragging=true;
     // 再表示をおこなう
    repaint();
  }
   // マウスのボタンが離された時のイベント
  public void mouseReleased(MouseEvent e){
     // マウスカーソルの位置を得る
    int mx=e.getX(),my=e.getY();
     // デバッグ用の表示
    System.out.println("mouseUp("+e+","+mx+","+my+")");
     // 配列linesのlineCount番目の始点を変更
    Line l=(Line)lineArray.elementAt(lineArray.size()-1);
    l.end_x=mx;
    l.end_y=my;
    dragging=false;
     // 再表示をおこなう
    repaint();
  }
  public void mouseClicked(MouseEvent e){}
  public void mouseEntered(MouseEvent e){}
  public void mouseExited(MouseEvent e){}
   // MouseMotionListenerを実装するためのメソッド
  public void mouseDragged(MouseEvent e){
     // マウスカーソルの位置を得る
    int mx=e.getX(),my=e.getY();
     // デバッグ用の表示
    System.out.println("mouseDrag("+e+","+mx+","+my+")");
     // 配列linesのlineCount番目の始点を変更
    Line l=(Line)lineArray.elementAt(lineArray.size()-1);
    l.end_x=mx;
    l.end_y=my;
     // 再表示をおこなう
    repaint();
  }
  public void mouseMoved(MouseEvent e){}
  // Delete ボタンが押された時の処理
  public void deleteLine(){
    int size;
    if((size=lineArray.size())>0){
      lineArray.removeElementAt(size-1);
      repaint();
    }
  }
  // Clear ボタンが押された時の処理
  public void clearLine(){
    lineArray.removeAllElements();
    repaint();
  }
}
// アプレットはpublicである必要
public class AppTest extends Applet implements ActionListener{
  MyCanvas myCanvas;
  Button deleteButton,clearButton;
  // コンストラクタは書かない.アプレット作成時に initが呼ばれる.
  // メニューバーは使えない
  public void init(){
    // パネル(ボタンなどを配置するための入れ物)部分を作成する.
    Panel panel=new Panel();
    panel.setLayout(new FlowLayout());
    panel.add(deleteButton=new Button("Delete"));
    deleteButton.addActionListener(this);
    panel.add(clearButton=new Button("Clear"));
    clearButton.addActionListener(this);
    // BorderLayoutを用いる.
    setLayout(new BorderLayout());
    // 上部に Panel
    add(panel,"North");
    // 下部に MyCanbasを配置する.
    add(myCanvas=new MyCanvas(),"South");
    // 部品をおさめるのに適当と思われるサイズにする.
    setSize(getPreferredSize());
    setVisible(true);
  }
  public void actionPerformed(ActionEvent e){
    System.out.println(e);
    Object source=e.getSource();
    // Deleteボタンが押された時
    if(source.equals(deleteButton)){
      myCanvas.deleteLine();
    }
    // Clearボタンが押された時
    else if(source.equals(clearButton)){
      myCanvas.clearLine();
    }
  }
}
ほとんど変更がなく書けるのが分かるだろう.これを実行するには, apptest.htmlという
<applet code="AppTest" width=600 height=450>
</applet>
といったファイルを同じディレクトリに作って,
appletviewer apptest.html
を実行する.あるいは,WWWブラウザでこのファイルをアクセスすると良い( apptest.html ).
先ほどのファイルのように,先頭にコメントで
// <applet code=AppTest width=600 height=450> </applet>
のように書いて置くと,
appletviewer AppTest.java
でアプレットを実行できる.ただし,WWWブラウザでアクセスするときは拡張 子をチェックするため,別に apptest.html が必要になる.
なお,NCのNetscapeは内部のJava処理系のバージョンが古いため,この授業に 従って作成したアプレットは実行できない.ただし,ツール->Javaを選択して, htmlファイル(Unixの~/java/apptest.htmlの場合は file:/nchome/java/apptest.html)を選択すると,NCローカルのJava処理系で アプレットを実行できる.

課題

前回,自分が作成したBallGameのプログラムにメニューバー,ボタンを加え て,それぞれに対して何らかの動作をするようにプログラムを書き直してくだ さい.それ以外のGUI部品を加えても構いません.

ヒント


課題をこなしたら, lectures.g99.cp1-ktanaka-W-Wed-5 のニュースグループに投稿すること.