| 目次| 1234567891011121314
| 資料| 予定| 課題| 宿題|

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

アプレットビューアと文字描画命令

今週は"appletviewer"を利用してアプレットを作ります. 今週は簡単なアプレット(HelloWorld.java) を作成し, appletviewerで動作させてみましょう(次に, "50,25"を変更してみる).

import java.applet.Applet;
import java.awt.Graphics;
/*
<applet code="HelloWorld" width=200 height=100></applet>
*/

public class HelloWorld extends Applet {
	public void paint(Graphics g){
	  
		g.drawString("Hello World!", 50, 25);
	}
}
	
  アプレットととして動作するプログラムは,「クラスのタイプ」を「アプレット」として作成する.コンパイル後,「アプレット実行」を選択し実行する.画面の表示サイズの確認が行われるので適当な大きさを指定し「アプレットビューアでアプレットを実行」がチェックされているか確認し「了解」を押して実行.

線の描画

線を描画するに は"drawLine"メソッドを利用する.その他のメソッドの一部も追々紹介します が,メソッドの一 覧も参考にしてください.
import java.applet.Applet;
import java.awt.Graphics;
/*
<applet code="Lines" width=150 height=150></applet>
*/

public class Lines extends Applet {
	public void paint(Graphics g){
		g.drawLine(10, 20, 90, 20);
		g.drawLine(10, 80, 90, 80);
		g.drawLine(20, 10, 20, 90);
		g.drawLine(80, 10, 80, 90);
	}
}

さまざまな図形

線の描画を紹介したが,その他の描画命令・色の扱いを紹介する. 以下の例では,多角形の描画に今回紹介した配列が用いられている.今回まで で主な描画命令は紹介した.アプレットのプログラムの中でも制御命令 (if,for,while,do〜while)は利用可能であり,これらを組み合わせるとより複 雑な図形を描くことができる.
import java.applet.Applet;
import java.awt.*;
/*
<APPLET CODE="GraphicsSample1.class" WIDTH=325 HEIGHT=250>
</APPLET>
*/

public class GraphicsSample1 extends Applet {
    public void paint(Graphics g) {
	g.setColor(Color.blue);
        g.drawString("Hello", 40, 50);

	g.setColor(Color.cyan);
        g.drawLine(100, 25, 150, 75);
        g.drawLine(150, 25, 100, 75);

	g.setColor(Color.green);
        g.drawRect(175, 25, 50, 50);
        g.fillRect(250, 25, 50, 50);

       	g.setColor(Color.magenta);
        g.drawRoundRect(25, 100, 50, 50, 10, 10);
        g.fillRoundRect(100, 100, 50, 50, 30, 10);

	g.setColor(Color.orange);
        g.drawOval(175, 100, 50, 50);
        g.fillOval(250, 100, 50, 30);

	g.setColor(Color.pink);
        g.drawArc(25, 175, 50, 50, 0, 90);
        g.fillArc(100, 175, 50, 30, 90, 120);

	g.setColor(Color.red);
        int x1[] = {195, 175, 185, 205, 215, 195};
        int y1[] = {175, 185, 205, 205, 185, 175};
        g.drawPolygon(x1, y1, 6); 

	g.setColor(Color.yellow);
        int x2[] = {270, 250, 260, 280, 290};
        int y2[] = {175, 185, 205, 205, 185};
        g.fillPolygon(x2, y2, 5); 
    }
}

簡単なイベント処理

イベントドリブン・プログラム

キーボードのキーが押されたとか,マウスが移動したといった事象をイベント (event)と呼ぶ.アプレットは基本的に,イベントの発生を監視し,イベント の発生に従って対応するメソッドに分岐する.このような方式のプログラムを イベントドリブン・プログラム (event-driven program) と呼ぶ.アプレット プログラム内で定義するinit メソッドや paint メソッドも,イベントによ り発生するメソッドである.

イベント処理の設定

イベント処理を設定するには,イベントが発生するオブジェクトにリスナーオ ブジェクトを組み込む必要がある.そのリスナーオブジェクトにイベント処理 メソッドを定義しておく.こうして,イベントが発生すると,イベントを処理 する場所(リスナー)に伝えられ,そこで定義されたイベント処理のメソッドが 実行される.
例えば,アプレットオブジェクトにマウスムーブイベント処理を設定するに は以下のようにする.ここでマウスムーブイベント処理とは,「マウスの移動 時のイベント処理」を意味する.
    public void init() {
        //リスナーオブジェクトの組み込み
	addMouseMotionListener(this);
    }

    //イベント処理メソッド
    public void mouseDragged(MouseEvent e) {
    }
    public void mouseMoved(MouseEvent e) {
         // マウスの移動時のイベント処理の内容
    }
addMouseMotionListener でマウスの移動時(ないしはドラッグ時)のイベント 処理を行う場所であるリスナーオブジェクトが組み込まれる. MouseMotionListenerを組み込んだ場合,mouseMoved,mouseDraggedと言う二つ のイベント処理メソッドを定義する必要がある.例のように処理内容がないイ ベントは内容が空で定義のみ行う.MouseEvent クラスの引数 e を用いて,マ ウスイベントに関する情報を取得することができる.例えば,移動時のマウス の位置を取得するには,getX() および getY() メソッドを使って,以下のよ うに記述すれば良い.
e.getX();  ←マウスの x 座標
e.getY();  ←マウスの y 座標
一般にイベント処理の設定は以下のように記述する.
    public void init() {
        //リスナーオブジェクトの組み込み
	add[イベントリスナークラス名](this);
    }

    //イベント処理メソッド[必要な数だけ]
    public void イベント処理メソッド名1(イベントクラス名 e) {
    }
    public void イベント処理メソッド名2(イベントクラス名 e) {
    }
イベントクラス名,イベントリスナークラス名,イベント処理メソッド名は 各々グループ化されている.以下の表に,マウスイベントおよびキーイベント 処理用のクラスとメソッドをまとめておく.
イベントクラス イベントリスナークラス名 イベント処理メソッド名 イベント発生時
MouseEvent MouseListener MouseClicked
MouseEntered
MouseExited
MousePressed
MouseReleased
マウスボタンをクリックした時
アプレット表示領域にマウスが入った時
アプレット表示領域からマウスが出た時
マウスボタンを押した時
マウスボタンを離した時
MouseEvent MouseMotionListener MouseDragged
MouseMoved
マウスボタンをドラッグした時
マウスを移動した時
KeyEvent KeyListener KeyPressed
KeyReleased
KeyTyped
キーを押した時
キーを離した時
キーをタイプした時

マウスムーブイベントの設定

実際に,マウスムーブイベントの設定を行ってみる.まずアプレット内でマウ スを移動させると楕円がマウスの移動にあわせて移動させ再表示(repaint)す るアプレットの例を以下に示す.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
/*
  <applet code="Ex12Applet1" width=300 height=300>
  </applet>
*/

public class Ex12Applet1 extends Applet implements MouseMotionListener {
    int x=10;
    int y=10;
    
    public void init() {
	addMouseMotionListener(this);
    }
  
    public void mouseDragged(MouseEvent me) {
    }
    public void mouseMoved(MouseEvent me) {
	x = me.getX();
	y = me.getY();
	repaint();
    }

    public void paint(Graphics g) {
	g.fillOval(x, y, 10, 10);
    }
}
   

マウスドロップイベントの設定

次に,マウスドロップイベントの設定を行ってみる.マウスドロップとは,画 面上のアイコンやイメージの上でマウスボタンをプレス・ドラッグして,目的 位置でマウスボタンをリリースすることを意味する.マウスドロップを実現す るには,mouseDragged,mousePressed,mouseReleased の 3 つのメソッドを 用いて,マウスドラッグ,マウスプレス,マウスリリース時のイベント処理を 定義する必要がある.

先ほどのアプレットと同じ楕円でマウスドロップを実現しているのが以下の プログラムである.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
/*
  <applet code="Ex12Applet2" width=300 height=300>
  </applet>
*/

public class Ex12Applet2 extends Applet
    implements MouseListener, MouseMotionListener {
    int x=10;
    int y=10;
    
    public void init() {
	addMouseMotionListener(this);
	addMouseListener(this);
    }
  
    public void mouseDragged(MouseEvent me) {
	x = me.getX();
	y = me.getY();
	repaint();
    }
    public void mouseMoved(MouseEvent me) {
    }

    public void mouseClicked(MouseEvent me) {
    }

    public void mouseEntered(MouseEvent me) {
    }

    public void mouseExited(MouseEvent me) {
    }
  
    public void mousePressed(MouseEvent me) {
	x = me.getX();
	y = me.getY();
	repaint();
    }

    public void mouseReleased(MouseEvent me) {
    }

    public void paint(Graphics g) {
	g.fillOval(x, y, 10, 10);
    }
}

マウスで自由曲線を描けるアプレット

最後にこれまで学んだ知識を使って,画面上にマウスで自由曲線を描けるよう なアプレットを作成してみる.これまでの画面への描画は,paint メソッドに (システム側から)渡される Graphic オブジェクトに対して行っていた.これ に対して,paint メソッド以外のメソッド,このアプレットでは mouseDragged メソッド,で画面への描画を行うには,予め init メソッドの 中で getGraphics() メソッドを用いてグラフィックス・オブジェクトを取得 しておき,そのオブジェクトに対して描画を行う必要がある.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
/*
  <applet code="Ex12Applet3" width=300 height=300>
  </applet>
*/

public class Ex12Applet3 extends Applet
    implements MouseListener, MouseMotionListener {
    int oldX, oldY;
    Graphics g;

    public void init() {
	g = getGraphics();        //グラフィックス・オブジェクトの取得.
	addMouseMotionListener(this);
	addMouseListener(this);
    }
  
    public void mouseDragged(MouseEvent me) {
	g.drawLine(oldX, oldY, me.getX(), me.getY());  
	//(oldX, oldY) と現在のマウス位置との間に直線を描く.
	oldX= me.getX();  //oldX, oldY の更新.
	oldY= me.getY();
    }
    public void mouseMoved(MouseEvent me) {
    }

    public void mouseClicked(MouseEvent me) {
    }

    public void mouseEntered(MouseEvent me) {
    }

    public void mouseExited(MouseEvent me) {
    }
  
    public void mousePressed(MouseEvent me) {
	oldX= me.getX();  //マウスプレス位置を oldX, oldY の初期値とする.
	oldY= me.getY();
    }

    public void mouseReleased(MouseEvent me) {
    }
}

アニメーションとマルチスレッド

 前回は,マウスの動きに追従して●が動くプログラムを紹介しました.今回 は,マウスによる指示なくプログラム自身で●マークを動かすプログラムを考 えます.簡単なアニメーションプログラムと言うことになります.プログラム で実現するアニメーションは,マウスでの指示に代わりに短い時間間隔で少し づつプログラム自身で位置を変えながら図形を描くことで実現できます.

 しかし,以前紹介したpaintメソッドの中で延々とアニメーションを表示する わけにはいきません.アプレットの親は,paintメソッドは1画面を描画してす ぐに終わることを期待しているので,paintメソッドが終わらないとまだ描画が 終わってないと思ってしまい実際に描画させません.このため,アニメーショ ンを行うには,一定の周期で繰り返しpaintメソッドを呼び出す仕組みが必要で す.

 Javaでは,これをマルチスレッドによって実現します.今まで作ってきたプ ログラムを考えましょう.プログラムがmainメソッドの最初から始まって終わ るまで,時間の経過とともに実行している場所を辿っていくことができます. この実行の流れのことをスレッドと呼びます.マルチスレッドとは,1つのプロ グラムの中でスレッドを複数動かすことです.マルチスレッドを使うと,プロ グラム中の複数の個所を同時に動かすことができます.

スレッドを作る方法

  1. クラス(ここではTとします)の中にvoid run()というメソッドを定義し ます.この中で,別のスレッドにさせたい処理を記述します.runメソッド は新しく作られるスレッドの実行開始点になります.
  2. クラスTを implements Runnable と宣言します.これは,スレッドと して実行可能なクラスであるという意味です.
  3. スレッドを作るには,Threadクラスのコンストラクタに,クラスTのオ ブジェクトを渡して,Threadクラスのオブジェクトを作ります.
  4. 作ったスレッドを走らせるためには,Threadクラスのstartメソッドを 使います.

アニメーションのプログラム

import java.awt.*;
import java.applet.*;

/*
  <applet code="AnimationApplet" width=300 height=300>
  </applet>
*/

public class AnimationApplet extends Applet implements Runnable {
    int x = 100;
    int y = 50;
    int dx = 5; // x方向の移動量
    int dy = 5; // y方向の移動量
    int width;  // 描画領域の幅
    int height; // 描画領域の高さ

    // 表示されている間は active が true になる
    boolean active = true;

    // startメソッドはアプレットの実行を開始するときに呼ばれる
    public void start() {
        // AppletクラスのgetBounds()メソッドを使って
        // アプレットの描画領域の大きさを取得
        Rectangle r = getBounds();
        width = r.width;
        height = r.height;

        Thread thread = new Thread(this);        // 新たにスレッドを作って
        thread.start();         // スレッドを開始する.

    }

    // stopメソッドはアプレットの実行を停止するときに呼ばれる
    public void stop() {
        active = false;
    }

    // スレッドの実行はrunメソッドから始まる
    public void run() {
        // 表示されている間繰り返す.独立したスレッドで
        // 動いていることに注意.
        while (active) {
            // 100ms 待つ.
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {}

            // 画面からはみ出しそうになったら反射させる
            if (x <= 5 || x >= width - 5) {
                dx = -dx;
            }
            if (y <= 5 || y >= height - 5) {
                dy = -dy;
            }
            // 位置をちょっとずらす
            x = x + dx;
            y = y + dy;

            // ブラウザに再描画を依頼する.Appletクラスの
            // repaintメソッドを呼ぶとブラウザが paint メソッドを
            // を呼び出してくれる.
            repaint();
        }
    }

    // 表示する
    public void paint(Graphics g) {
        g.fillOval(x - 5, y - 5, 10, 10);
    }
}

startメソッドが呼ばれると新しいスレッドの実行がはじまります.スレッ ドはrunメソッドから開始します.作られたスレッドは,stopメソッドが呼ばれ るまで(ブラウザとは独立して)延々と処理をし続けます.

課題

    アプレットについては実行結果の画面は不要です.

  1. イニシャルを印字するプログラムのアプレット版を作成しなさい(drawString)
  2. アプレットに線・円等を引いてイニシャルを書くプログラムを書きなさい.
  3. プログラムEx12Applet1を,マウスムーブ時ではなくマウスプレス時の イベント処理に書き改めてみよ(つまりドラッグに反応しない).
  4. プログラムEx12Applet2を作成・コンパイル・実行してみよ.
  5. プログラムEx12Applet3を作成,コンパイル,実行し,様々な自由曲線 を描いてみよ.

| 目次| 1234567891011121314
| 資料| 予定| 課題| 宿題| Last modified: Thu Jan 12 14:42:48 JST 2017