Javaとイベントの処理

ほとんどのプログラムは、有用であるために、ユーザーからのコマンドに応答する必要があります。そのために、Javaプログラムは、ユーザーのアクションを説明するイベントに依存しています。

先月、Javaクラスライブラリの抽象ウィンドウツールキットによって提供されるコンポーネントからグラフィカルユーザーインターフェイスを組み立てる方法を示しました。そのようなインターフェースをいくつか組み立てた後、イベント処理のトピックについて簡単に話しましたが、AWTによって実装されたイベント処理の完全な説明には至りませんでした。今月は、中断したところから再開します。

イベント駆動型になる

遠い昔、ユーザーが何をしているのかを知りたがっているプログラムは、そのような情報自体を積極的に収集しなければなりませんでした。実際には、これは、プログラムがそれ自体を初期化した後、ユーザーが何か面白いことをしているかどうかを繰り返し確認する大きなループに入ったことを意味しました(たとえば、ボタンを押す、キーに触れる、スライダーを動かす、マウスを動かす)その後、適切なアクションを実行しました。この手法は、ポーリングとして知られています。

ポーリングは仕事を成し遂げますが、2つの関連する理由から、現代​​のアプリケーションで使用すると扱いにくい傾向があります。まず、ポーリングを使用すると、すべてのイベント処理コードが1つの場所(大きなループ内)にプッシュされる傾向があります。第二に、大きなループ内で結果として生じる相互作用は複雑になる傾向があります。さらに、ポーリングでは、プログラムがループ内にとどまり、CPUサイクルを消費し、ユーザーが何かを実行するのを待つ必要があります。これは、貴重なリソースの深刻な浪費です。

AWTは、すべての最新のウィンドウシステムの根底にある別のパラダイム(イベント駆動型プログラミング)を採用することで、これらの問題を解決しました。AWT内では、すべてのユーザーアクションは、イベントと呼ばれる抽象的なもののセットに属します。イベントは、特定のユーザーアクションを十分に詳細に説明します。プログラムがユーザー生成イベントをアクティブに収集するのではなく、Javaランタイムは、興味深いイベントが発生したときにプログラムに通知します。この方法でユーザーインタラクションを処理するプログラムは、イベント駆動型と呼ばれます。

イベントクラス

イベントクラスは、イベントゲームの主要なプレーヤーです。これは、ユーザーが生成したすべてのイベントの基本的な特性をキャプチャしようとします。表1に、イベントクラスによって提供されるパブリックデータメンバーを示します。

タイプ 名前 説明
オブジェクト 目標 最初にイベントを受信したコンポーネントへの参照。
長いです いつ イベントが発生した時点。
int id イベントタイプ(詳細については、「イベントタイプ」のセクションを参照してください)。
int バツ 現在イベントを処理しているコンポーネントに関連してアクションが発生したx座標。特定のイベントについて、イベントがコンポーネント階層を上に移動すると、x座標の値が変化します。座標平面の原点は、コンポーネントの左上隅にあります。
int y 現在イベントを処理しているコンポーネントに関連してアクションが発生したy座標。特定のイベントについて、イベントがコンポーネント階層を上に移動すると、y座標の値が変化します。座標平面の原点は、コンポーネントの左上隅にあります。
int キー キーボードイベントの場合、押されたばかりのキーのキーコード。その値は通常、キーが表す文字のUnicode値になります。その他の可能性には、特殊キーHOME、END、F1、F2などの値が含まれます。
int 修飾子 値SHIFT_MASK、CTRL_MASK、META_MASK、およびALT_MASKの算術的または 'dの組み合わせ。その値は、それぞれ、Shiftキー、Controlキー、Metaキー、およびAltキーの状態を表します。
int clickCount 連続したマウスクリックの数。このデータメンバーは、MOUSE_DOWNイベントでのみ重要です。
オブジェクト arg イベントに依存する引数。Buttonオブジェクトの場合、このオブジェクトはボタンのテクスチャラベルを含むStringオブジェクトです。
表1:クラスイベントによって提供される公開データメンバー

イベントのディスパッチと伝播というタイトルのセクションで説明するように、クラスEventのインスタンスは、通常、Javaランタイムシステムによって作成されます。ただし、プログラムがイベントを作成し、そのpostEvent()メソッドを介してコンポーネントに送信することは可能です。

イベントタイプ

上記のように、Eventクラスはユーザーインターフェイスイベントのモデルです。イベントは当然、イベントのタイプに基づいてカテゴリに分類されます(イベントタイプはidデータメンバーによって示されます)。表2に、AWTによって定義されたすべてのイベントを、カテゴリー別にソートして示します。

表2:AWTによって定義されたイベント、カテゴリー別にソート

イベント生成の動作を確認することは有益な場合があります。図1のボタンを押すと、ブラウザが受信したイベントに関するイベント情報を表示するイベントブラウザが作成されます。イベントブラウザのソースコードはこちらから入手できます。

このアプレットを表示するには、Java対応のブラウザが必要です

図1:実行中のイベント生成

イベントのディスパッチと伝播

Consider the applet in Figure 2. It consists of two instances of the Button class, embedded within an instance of the Panel class. This instance of the Panel class is itself embedded within another instance of the Panel class. The latter instance of the Panel class sits below an instance of class TextArea, and both instances are embedded within an instance of the Applet class. Figure 3 presents the elements that make up this applet laid out as a tree, with the TextArea and Button instances as the leaves, and an Applet instance as the root. (For more information about the hierarchical layout of components in a user interface, read last month's introduction to the AWT.)

You need a Java-enabled browser to view this applet

Figure 2: Classes embedded within classes

Figure 3: Applet elements tree (hierarchy)

When a user interacts with the applet in Figure 2, the Java run-time system creates an instance of class Event and fills its data members with information describing the action. The Java run-time system then allows the applet to handle the event. It begins with the component that initially received the event (for instance, the button that was clicked) and moves up the component tree, component by component, until it reaches the container at the top of the tree. Along the way, each component has the opportunity to ignore the event or to react to it in one (or more) of the following ways:

  • Modify the data members of the Event instance
  • Take action and perform some computation based on the information contained in the event
  • Indicate to the Java run-time system that the event should propagate no further up the tree

The Java run-time system passes event information to a component via the component's handleEvent() method. All valid handleEvent() methods must be of the form

public boolean handleEvent(Event e) 

An event handler requires a single piece of information: a reference to the instance of the Event class containing information about the event that just occurred.

The value returned from the handleEvent() method is important. It indicates to the Java run-time system whether or not the event has been completely handled within the event handler. A true value indicates that the event has been handled and propagation should stop. A false value indicates that the event has been ignored, could not be handled, or has been handled incompletely and should continue up the tree.

Consider the following description of an imaginary user's interaction with the applet in Figure 2. The user clicks on the button labeled "One." The Java language run-time system gathers information about the event (the number of clicks, the location of the click, the time the click occurred, and the component that received the click) and packages that information in an instance of the Event class. The Java run-time system then begins at the component that was clicked (in this case, the Button labeled "One") and, via a call to the component's handleEvent() method, offers the component a chance to react to the event. If the component does not handle the event or handles the event incompletely (indicated by a return value of false), the Java run-time system offers the Event instance to the next higher component in the tree -- in this case an instance of the Panel class. The Java run-time system continues in this manner until the event is handled or the run-time system runs out of components to try. Figure 4 illustrates the path of this event as the applet attempts to handle it.

Figure 4: The path of an event

Each component making up the applet in Figure 2 adds a line to the TextArea object that indicates it received an event. It then allows the event to propagate to the next component in the tree. Listing 1 contains the code for a typical handleEvent() method. The complete source code for this applet is available here.

public boolean handleEvent(Event evt) { if (evt.id == Event.ACTION_EVENT) { ta.appendText("Panel " + str + " saw action...\n"); } else if (evt.id == Event.MOUSE_DOWN) { ta.appendText("Panel " + str + " saw mouse down...\n"); }

return super.handleEvent(evt); }

Listing 1: A typical handleEvent() method

Event helper methods

The handleEvent() method is one place a programmer can put application code for handling events. Occasionally, however, a component will only be interested in events of a certain type (for example, mouse events). In these cases, the programmer can place the code in a helper method, rather than placing it in the handleEvent() method.

Here is a list of the helper methods available to programmers. There are no helper methods for certain types of events.

action(Event evt, Object what)

gotFocus(Event evt, Object what)

lostFocus(Event evt, Object what)

mouseEnter(Event evt, int x, int y)

mouseExit(Event evt, int x, int y)

mouseMove(Event evt, int x, int y)

mouseUp(Event evt, int x, int y)

mouseDown(Event evt, int x, int y)

mouseDrag(Event evt, int x, int y)

keyDown(Event evt, int key)

keyUp(Event evt, int key)

false to indicate that the helper method did not handle the event.

The implementation of the handleEvent() method provided by class Component invokes each helper method. For this reason, it is important that the redefined implementations of the handleEvent() method in derived classes always end with the statement

return super.handleEvent(e);

The code in Listing 2 illustrates this rule.

public boolean handleEvent(Event e) { if (e.target instanceof MyButton) { // do something... return true; }

return super.handleEvent(e); }

Listing 2: Rule for ending statement in handleEvent() method

Failure to follow this simple rule will prevent the proper invocation of helper methods.

Figure 5 contains an applet that handles mouse events solely through code placed in helper methods. The source code is available here.

Event evt The next event in a linked list of events.
Window events
Window events are generated in response to changes in the state of a window, frame, or dialog.
Event ID
WINDOW_DESTROY 201
WINDOW_EXPOSE 202
WINDOW_ICONIFY 203
WINDOW_DEICONIFY 204
WINDOW_MOVED 205
Keyboard events
Keyboard events are generated in response to keys pressed and released while a component has input focus.
Event ID
KEY_PRESS 401
KEY_RELEASE 402
KEY_ACTION 403
KEY_ACTION_RELEASE 404
Mouse events
Mouse events are generated in response to mouse actions occurring within the boundary of a component.
Event ID
MOUSE_DOWN 501
MOUSE_UP 502
MOUSE_MOVE 503
MOUSE_ENTER 504
MOUSE_EXIT 505
MOUSE_DRAG 506
Scroll events
Scroll events are generated in response to manipulation of scrollbars.
Event ID
SCROLL_LINE_UP 601
SCROLL_LINE_DOWN 602
SCROLL_PAGE_UP 603
SCROLL_PAGE_DOWN 604
SCROLL_ABSOLUTE 605
List events
List events are generated in response to selections made to a list.
Event ID
LIST_SELECT 701
LIST_DESELECT 702
Miscellaneous events
Miscellaneous events are generated in response to a variety of actions.
Event ID
ACTION_EVENT 1001
LOAD_FILE 1002
SAVE_FILE 1003
GOT_FOCUS 1004
LOST_FOCUS 1005
Todd Sundstedは、コンピューターがデスクトップモデルで利用できるようになって以来、プログラミングを行ってきました。Toddは、もともとC ++で分散オブジェクトアプリケーションを構築することに興味を持っていましたが、Javaがそのようなことの明白な選択になったときに、Javaプログラミング言語に移行しました。Toddは、執筆に加えて、米国南東部の企業にインターネットおよびWebアプリケーションのコンサルティングサービスを提供しています。

このトピックの詳細

  • MaryCampioneとKathyWalrathによるJavaチュートリアル。オンラインドラフトバージョンは、// java.sun.com/tutorial/index.htmlで入手できます。

このストーリー「Javaとイベント処理」は、もともとJavaWorldによって公開されました。