アプレットプログラミング(2)


アプレットの多くは,前回までのようにWWWブラウザのウィンドウ内だけで実 現されている.AppletPanelの子 クラスとして定義されていて,性質の多くを引き継いでいるからである.

しかし,WWWブラウザ内で収まらずに,アプレット内でFrame等の他のGUI部品 を作成することが可能である.この時,

という注意を守らないと,WWWブラウザ上で Javaプログラムが動き続けたり, 余計なWindowだらけになって困る.

例として,CanvasTestを別ウィンドウのアプレットにする例を示す.



// 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();
  }
}

class CanvasTest extends Frame implements ActionListener{
  MenuBar menuBar;
  Menu fileMenu,editMenu;
  MyCanvas myCanvas;
  Button deleteButton,clearButton;
  CanvasTest(){
    super("CanvasTest");
    // メニューバーを作成する
    menuBar=new MenuBar();
    // Fileというメニュー
    fileMenu=new Menu("File");
    fileMenu.add("Exit");
    // メニューが選択された時に, CanvasTestがイベントを受け取る
    fileMenu.addActionListener(this);
    // メニューバーにfileMenuを加える.
    menuBar.add(fileMenu);
    editMenu=new Menu("Edit");
    editMenu.add("Clear");
    editMenu.add("Delete");
    editMenu.addActionListener(this);
    menuBar.add(editMenu);
    // Frameにメニューバーを付け加える.
    setMenuBar(menuBar);
    // パネル(ボタンなどを配置するための入れ物)部分を作成する.
    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");
    // キー入力がbuttonに横取りされないようにするため
    deleteButton.addKeyListener(myCanvas);
    clearButton.addKeyListener(myCanvas);
    // 部品をおさめるのに適当と思われるサイズにする.
    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();
    }
    // [Edit]メニューのどれかが選択された時
    else if(source.equals(editMenu)){
      String command=e.getActionCommand();
      // Delete メニューが選択された時
      if(command.equals("Delete")){
        myCanvas.deleteLine();
      }
      // Clear メニューが選択された時
      else if(command.equals("Clear")){
        myCanvas.clearLine();
      }
    }
    // [File]メニューのどれかが選択された時
    else if(source.equals(fileMenu)){
      String command=e.getActionCommand();
      // Exitメニューが選択された時
      if(command.equals("Exit")){
        System.exit(0);
      }
    }
  }
  public static void main(String args[]) {
     // CanvasTestのインスタンスを作成 frameに代入
    CanvasTest frame=new CanvasTest();
  }
}
public class CanvasTestApplet extends Applet{
  CanvasTest frame;
  public void init(){
    frame=new CanvasTest();
  }
  public void start(){
    frame.setVisible(true);
    //    frame.start();
  }
  public void stop(){
    frame.setVisible(false);
    //frame.stop();
  }
}

課題

動くアプレットを作りなさい.以下の条件を満たすものです.


課題をこなしたら,センターのUnixサーバ上のNetscapeから他ユーザがアプレッ トを実行できる状態にして,アプレットのURL,ソースと簡単な説明を lectures.g99.cp1-ktanaka-W-Wed-5 のニュースグループに投稿すること.