Java のイベント処理のしかたについて説明します。
前回、ボタンを使ってレイアウトを3種類見てきました。これらのボタンを押しても何も起こりませんでしたが、これはイベント処理をしていないからです。
Java ではイベント処理を行う場合、 DelegationEventModel というモデルを使います。このモデルを使っていく場合、2つの言葉が出てきます。1つはイベントソース、もう1つはリスナです。
たとえば、「ボタンを押すとメッセージを表示する」という処理を書きたい場合、ボタンを押すと「ボタンが押された」というイベントが発生します。そして、このイベント発生を受けて、メッセージを表示する処理が動きだします。
このとき、イベントを発生させることになったコンポーネント、つまりボタンがイベントソースとなります。そして、メッセージを表示する処理を行うものがリスナになります。
イベントソースはこの後に出てくる Button や List のようなコンポーネントのクラスが担当します。イベント処理はリスナが担当します。この2つは基本的には別々の物なので、「このイベントソースでイベントが発生したら、 このリスナで処理をする」という関連付けをしてやらなければなりません。この関連づけのことをリスナの登録といいます。Java ではイベントソースにリスナを登録することで、関連づけを行います。
先ほどのボタンを押すという例に戻ってイベント処理の流れを追っていきます。 Java ではボタンを押したとき、ActionEvent という名前のイベントが発生します。 ActionEvent はイベント名ですが、これは java.awt.event パッケージに定義されているクラス名でもあります。
Java ではイベントが発生すると、イベントオブジェクトというものが生成されます。ActionEvent が発生すると、ActionEvent オブジェクトが生成されます。このイベントオブジェクトにはどこでどんなイベントが発生したか、というような情報が入っています。
イベントが発生すると、ボタンに登録されているリスナに「イベントが発生しましたよ」 という通知が行きます。このとき、同時にイベントオブジェクトもリスナに渡します。通知を受けたリスナは実際にその後のイベント処理(メッセージの表示など)を行います。
このとき、リスナではイベント処理用のメソッドとしてあらかじめ決められているメソッドを実行します。ActionEvent の場合には actionPerformed( ) というメソッドを実行すると決められています。
イベントソースやイベントは自分で作ることもできます。
イベントを処理するリスナには作り方にいくつかのルールがあります。1つは、イベントを処理するためのメソッドが決まっているということ。もう1つは、イベント処理用のメソッドはインタフェースに定義されているので、これを実装したクラスを作るということです。
ActionEvent の場合、このイベントを処理するためのメソッドは、 actionPerformed(ActionEvent e) という名前のメソッド、と決められています。そして、このメソッドは自分で勝手に作るのではなく、 ActionListener というインタフェースに定義されている actionPerformed( ) をオーバーライドする、というように決まっています。
ですから、ActionEvent を処理するリスナのクラスは、
// MyHandler.java
import java.awt.event.*;
class MyHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("ボタンがおされたよ");
}
}
|
というように書いていきます。 ActionEvent クラス、ActionListener インタフェースが java.awt.event パッケージにあるのでインポートして使います。
これでリスナはできあがったので、次にボタンとこのリスナの関連づけ、リスナの登録を行います。 ActionEvent を処理するリスナを登録するメソッドは、 addActionListener(ActionListener l) という形式のメソッドです。この登録用のメソッドは各コンポーネントのクラスが持っています。ボタンの場合は Button クラスに定義されています。
addActionListner の引数の型は ActionListener 型になっていますが、 これは Actionlistener インタフェースを実装したクラスのオブジェクトが指定できるという意味です。
次の例では1つのソースファイル内に2つのクラスを定義していますが、別のソースファイルに定義しても構いません。
ActionTest.java
// ActionTest.java
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class ActionTest extends Applet {
public void init() {
// ボタン作成・追加
Button b = new Button("OK");
add(b);
// リスナ登録 (ボタンにリスナを登録する)
MyHandler handle = new MyHandler();
b.addActionListener(handle);
}
}
// リスナ
class MyHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("ボタンがおされたよ");
}
}
|
ActionTest.html
<APPLET CODE=ActionTest.class width=200 height=100>
</APPLET>
|
実行例 (画像をクリックすると実際のActionTest.html のアプレットが起動します)