Java UI の概説 |
ユーザが、たとえばクリックしたり改行キーを押すなどして、ある コンポーネント に対して何 らかの行動を起こすと、Event オブジェクトが作成される。 AWT のイベント処理システムは、Event を コンポーネント 階層の上方向に渡していき、 ウィンドウシステムがそのイベントを完全に処理する前に各 コンポーネント がイベント に反応することができる。各 コンポーネント のイベントハンドラは、イベントを無視す ることもあるし、以下のどれかの方法で反応することもできる。
- Event インスタンスを変更した後で、さらに上の階層へ渡す -- たとえば、すべての文字を 大文字で表示するような TextField サブクラスで小文字表示のキー操作に対して大文字に変更をするように Event を変更する。
- イベントに何か別の方法で反応する -- たとえば、テキストフィールドのコンテンツを処理するメソッドを呼び出すことによ って、TextField サブクラス (または TextField の Container) が改行キーの押下 に反応できるようにする。
- イベントのそれ以上の処理を停止する -- たとえば、無効な文字がテキストフィールドに入力された場合、イベントハンドラは その Event がそれ以上処理されないよう停止することができる。
コンポーネント から見ると、AWT のイベント処理システムはイベントフィルタ システムに近い。 ウィンドウシステム依存コードがあるイベントを生成しても、ウィンドウシステム依 存コードがそのイベントを完全に処理するより先に、それを変更したり、反応したり 、破棄したりする機会が コンポーネント に与えられる。 [チェック -- これは適切かつ正しい言い方か?] 次の [存在しない] 図に、プログラム例 の TextField イベントのイベ ント処理のチェーンを示す。
注: 現在のリリースでは、マウスイベントは、ウィンドウシステム依存コードが完全に処 理した後で、コンポーネント に転送される。 このため、現在のリリースではコンポーネントはキーボード のイベントをすべて捕らえることにな っているが、マウス イベントについては捕らえること ができない。
イベントオブジェクト
それぞれのイベントによってEvent オブジェクトが生成される。 Event オブジェクトには以下の情報が含まれている。
- イベントのタイプ -- たとえば、キー押下やマウスクリック、または抽象度の 高い "action" やウィンドウのアイコン化など。
- イベントの "target" となったオブジェクト -- たとえば、ユーザがクリックし たスクリーン上のボタンに対応する Button オブジェクト、ユーザが入力したテキストフィール ドに対応する TextField オブジェクトなど。
- イベントがいつ発生したかを示す時刻表示。
- イベントが発生した位置 (x,y)。
- 押されたキー (キーボードイベントの場合)。
- その Event に関連した任意の引数 (コンポーネント 上に表示する文字列など)。
- イベントが発生したときの修飾キーの状態。
イベントハンドラの実装方法
コンポーネント はhandleEvent()
メソッドを実装するか、またはイベントタ イプに特有のメソッドを実装することによって、イベントに反応できるよう になる。 後者の方法が機能するのは、handleEvent()
メソッドのデフォルトの (コンポーネント の) 定義がそのイベントタイプに特有のメソッドを呼び出すようになっているからである。このようなイベント特有のメソッドには、mous eEnter()
、
mouseExit()
、
mouse Move()
、
mouseUp ()
、
mouse Down()
、
mouse Drag()
、
keyDown ()
、
action()
がある。重要: すべてのイベントハンドラメソッドは高速に実行されなければならない! そうしな いと、プログラムの目で見える性能が大きく損なわれる。 イベントの結果として何か時間のかかる操作を実行する必要がある場合は、別のスレ ッドを始動して (または別のスレッドへ要求を送信して) その操作を実行すべきであ る。 スレッドの使用法については、スレッドのコントロール を参照する。
プログラム例では、すべてのイベント処理は ConversionPanel で実行されている。 これらはテキストフィールド (TextField) とポップアップリスト (Choice) で発生したイベントの捕捉には
action()
を使用し、スラ イダ (Scrollbar) で発生したイベントの捕捉にはhandleEvent()
メソッドを使用している。次に、
action()
およびhandleEvent()
メソッドの ConversionPanel での実装を示す。このメソッドは、 ConversionPanel のスライダとテキストフィールドがどちらも同じ値を示すようにし 、 その後、Converter オブジェクトに他の ConversionPanel を更新するよう要求して いるだけである。/** 制御盤でのユーザ動作に反応する */ public boolean action(Event e, Object arg) { if (e.target instanceof TextField) { setSliderValue(getValue()); controller.convert(this); return true; } if (e.target instanceof Choice) { controller.convert(this); return true; } return false; } /** スライダーに反応する */ public boolean handleEvent(Event e) { if (e.target instanceof Scrollbar) { textField.setText(String.valueOf(slider.getValue())); controller.convert(this); } return super.handleEvent(e); }action()
メソッドは、イベ ントを処理したのであれば true を返し、そうでなければ false を 返す。このようにして、コンポーネント階層の上位にあるものもイベントの発生したオブジェクトの様子を 知ることができるのである。handleEvent()
メソッドは、すべてのイベントが完全に処理されるよ うに、常にsuper.handleEvent()
を返す。注:
handleEvent()
が (そのスーパークラスの実装を呼び出す代わりに)true
かfalse
を返したら、action()
メ ソッドは決して呼び出されない ことになってしまう。どうしても必要なと き以外はhandleEvent()
を実装しないよう推奨するのは、このような リスクがあることも理由の 1 つである。
Java UI の概説