マウスイベント


代行イベントモデル

さて、せっかくアニメーションもできるようになったけど、何か物足りません
それはユーザーとの対話がないからではないでしょうか?

といっても、今作っているアプリケーションはGUIというマルチプログラム環境下です
MS-DOSやUNIXのように、コマンドラインによる一対一の処理ではありません
この意味は大きく、出力にSystem.outが使えないのと同じで標準入力も使えないというこです

GUI未経験者ならば、これから「イベント」を学習しなければなりません
イベントはコマンドラインとはまったく逆の考え方、プログラム方法で進行します
コマンドラインでのプログラムは常にプログラム及びプログラマが処理の流れの独裁政権を持っています
プログラムが実行されれば、その流れはプログラマの思うがままでした

しかし、GUIの場合は逆で完全民主主義なのです
プログラムは常にユーザーという、コンピュータの民の要求に沿って動きます
ユーザーがある動作をすれば、その動作に有効なメソッドを呼び出すというのがイベントモデルなのです

そして、ユーザーの動作のことをイベントと呼びます
イベントの種類は様々で、ボタンを押したりキーボードを押したりなどです
Javaのイベントモデルは、継承ベースのイベントモデルであるJDK1.02以前の旧式と
現在使われている代行(委譲)イベントモデルの二種類が存在します
当然、過去のイベントモデルは推奨されないので、ここでは代行イベントモデルを説明します


さて、イベントモデルに付いて簡単な説明をしたところで
さっそくですが、マウスによるイベントを発生させてみましょう
イベント発生の対象はAppletクラス、つまりアプレットそのものです
イベントを受けるのにはComponentクラスのaddMouseListener()メソッドを利用します

public synchronized void addMouseListener( MouseListener lis )

lisにはjava.awt.event.MouseListenerインタフェイスをインプリメントしているクラスのオブジェクトを渡します
これはコンポーネントからのイベントの監視を追加するものです
MouseListenerインタフェイスで定義できるイベントタイプは次の通りです

public abstract void mouseClicked( MouseEvent e ) コンポーネント上でクリック
public abstract void mouseEntered( MouseEvent e ) コンポーネントに入る
public abstract void mouseExited( MouseEvent e ) コンポーネントから出る
public abstract void mousePressed( MouseEvent e ) コンポーネント上でマウスボタンを押す
public abstract void mouseReleased( MouseEvent e ) コンポーネント上でマウスボタンを離す

右クリックや左クリックといった指定はありません
これは、マウスのボタンの数がプラットフォームによって異なるためです(Macだと1つ、Winだと2つあるでしょ)
これらのメソッドが受け取る引数はjava.awt.event.MouseEventというイベントクラスです
適切なイベントが発生した時、プログラムは適切なメソッドを呼び出します
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

/*	<applet code="App23.class" width="300"height="300">
 	</applet>
*/

public class App23 extends Applet implements MouseListener {
	public void init() {
		addMouseListener(this);
		setBackground(new Color(0xff , 0xff , 0xff));
	}
	public void mouseClicked(MouseEvent e) {
		setBackground(new Color(0xff , 0 , 0));
		repaint();
	}
	public void mouseEntered(MouseEvent e) {
		setBackground(new Color(0 , 0 , 0xff));
		repaint();
	}
	public void mouseExited(MouseEvent e) { 
		setBackground(new Color(0 , 0xff , 0));
		repaint();
	}
	public void mousePressed(MouseEvent e) { }
	public void mouseReleased(MouseEvent e) { }
}
アプレット

このアプレットは、マウスが上に乗る、マウスが離れる、クリックする、のイベントに対応しています
これらのイベントが発生すれば、適応するメソッドが呼び出されます
インターフェイスをインプリメントしているので、必ずインターフェイスのメソッドを実装してください

ここで、上のプログラムが何をしているのか、正確な説明をします
プログラムは、何らかのイベントが発生しているのかどうかを確認しています
これらの通知を登録したり解除したりするメソッドの提供者こそがイベントソース(源流)です
この場では addMouseListener() メソッドがその役割を果たしています

addMouseListener()で指定したMouseListenerで、イベントを受け取る監視を追加します
イベント通知の監視者をイベントリスナーと呼びます
イベントが発生すると、イベントをリスナーの適切なメソッドを呼び出しイベントを受け取り処理されます
MouseEventイベントクラスに対応しているリスナーインタフェイスは、MouseListenerとMouseMotionListenerです
MouseMotionListenerについては、次のサンプルで紹介いたします


イベントクラス

イベントが発生した時、イベントクラスはリスナーインタフェイスに渡されます
この値は、イベントの詳細を受け取るのに必要です
たとえば、マウスイベントならばマウスがどの位置でクリックされたのかなどを知る必要がある場合があります
このような場合、イベントクラスのカプセル化されたデータを利用します

ここでお絵描きソフトを作成してみようと思います
といっても、非常に簡単でいいかげんなものですが…

お絵描きをするには、マウスがコンポーネント上のどの位置にあるかを知る必要があります
これを知るにはMouseEventクラスのgetX()getY()メソッドを使用します

public int getX()
public int getY()

getX()は横の位置、getY()は縦の位置を返します
ここで得られる値はコンポーネントと相対の位置なので、そのまま使用できます
(普段はMouseEventクラスのメソッドは、このくらいしか使わないと思います…)

次に、イベントの登録ですが addMouseListener() では実現できません
お絵描きをする場合はマウスの動きを追う必要があります
つまり、ドラッグ対応にしなければなりません
マウスのドラッグには、ComponentクラスのaddMouseMotionListener()メソッドが有効です

public synchronized void addMouseMotionListener( MouseMotionListener lis )

ここでjava.awt.event.MouseMotionListenerインタフェイスという
先ほど少しだけお話したインタフェイスが出てきました

このインタフェイスは、次の二つのメソッドを宣言しています

public abstract void mouseDragged( MouseEvent e ) ボタンを押しながらドラッグ
public abstract void mouseMoved( MouseEvent e ) ボタンを押さずに移動

インターフェイスはMouseEventイベントを受け取るので、基本的な作業は先程と変わりません
あとはドラッグされたマウス位置に、fillOvalなどを用いて図を書いてやれば良いのです
ただし、ダブルバッファリングを行うのを忘れないでくださいね
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

/*	<applet code="App24.class" width="300"height="300">
 	</applet>
*/

public class App24 extends Applet implements MouseMotionListener {
	int x = -5 , y = -5;

	public void init() {
		addMouseMotionListener(this);
		setBackground(Color.white);
	}
	public void mouseDragged( MouseEvent e ) {
		x = e.getX();
		y = e.getY();

		repaint();
	}
	public void mouseMoved( MouseEvent e ) { }

	public void update(Graphics g) {
		paint(g);
	}

	public void paint(Graphics g) {
		g.fillOval(x , y , 3 , 3 );
	}
}
アプレット

マウスをドラッグすると、そこにfillOval()による点が描かれます
このプログラムはupdate()をオーバーライドすることで、画面に描画しているにすぎません
一度画面を隠すと線(点)は消えるし、しかもxとy値が最後の位置で残っているので
再描画下時に、その位置に不自然に点が現れます

この現象を回避するには、ダブルバッファリングなどを使用してください
または、描画した後にx,y値をマイナスにしてイベントを待つなどの手もあります



前のページへ戻る次のページへ