イベントとイベントハンドラ¶
例)Touchイベントを受け取るイベントハンドラ
function onTouch(e) {
title = "Hello!";
}
e.from |
イベントの発信元オブジェクト |
e.eventName |
イベント名 |
function onLostFocus(e) {
if (e.from instanceof TextBox) {
if (e.from.value == "") {
e.from.bgColor = Color.RED; # 未入力ならば赤色
} else {
e.from.bgColor = Color.STD; # 入力済みであればデフォルト色(白色)
}
}
}
汎用イベントハンドラ¶
on にイベント名を続けた名前で定義します。onEvent という名前のFunctionを定義すると、イベント名によらずイベントを受け取る汎用イベントハンドラになります。onEvent は、通常のイベントハンドラより先に呼び出されます。eventName プロパティを参照して処理するイベントを選択できます。true を返した場合、そのイベントの伝播を停止します。false または値を返さなかった場合は、通常のイベントハンドラの検索とイベントの伝播が続行されます。KeyDown イベントの伝播を汎用イベントハンドラで停止しています。onKeyDown は呼び出されません。KeyDown 以外のイベントでは onEvent が false を返すため、通常のイベントハンドラが呼び出されます。Form form1 {
function onEvent(e) {
if (e.eventName == "KeyDown") {
return true; # KeyDownイベントの伝播を停止
} else {
return false; # その他のイベントは通常どおり処理
}
}
function onKeyDown(e) {
# onEventがtrueを返すため、このイベントハンドラは呼び出されません。
}
}
onEvent でイベントを停止せず、イベントに応じた処理だけを行いたい場合は、false を返すか、戻り値を指定しません。e.from、イベント名は e.eventName で参照できます。同期イベント処理のタイミング¶
同期イベントは、イベントが発生した時点でイベントキューを経由せずに直接イベントハンドラを実行します。
そのため、同期イベントのハンドリングは、関数の呼び出しと同じような流れで実行されます。
var numA = new Number {
# デフォルトプロパティの変更に対しchangeイベントを発行します
useChange = true;
# デフォルトプロパティが変化した際に呼ばれるイベントハンドラです
function onChange(e) {
print("2");
}
};
# 下記の処理を実行すると、1 → 2 → 3 の順で出力されます
print("1");
numA.value = 100; # 代入処理を行った瞬間、onChangeイベントが発生します
print("3");
非同期イベント処理のタイミング¶
ケース1
1個目のイベントがキューに格納された後、イベントハンドラが起動される。
ケース2
2個目のイベントがキューに格納された後、イベントハンドラが起動される。
ケース3
すべてのイベントがイベントキューに格納された後、イベントハンドラが起動される。
通常、イベントの発生は何か状態が変化したときに発生します。
連続したイベントは、状態が連続して変化していることになります。
上記のケースのように連続した非同期イベントで、イベントの要因となった状態をスクリプト中で参照すると、 イベントハンドラが実行されるタイミングにより、参照した結果は異なることがあります。
例えば、非同期イベントでオブジェクトの状態変化を通知するような場合、 ケース1の場合ではイベントハンドラの1回目の呼び出しでは1個目のイベントが発生した際の値が取得できます。 ケース3の場合、イベントハンドラの1回目の呼び出しでは3個目のイベントが発生した際の値が取得できます。
最終的にはどのケースでも、イベントと同じ数だけイベントハンドラは起動されますが、 オブジェクトプロパティの現在値とイベントを起こしたときの状態は必ずしも一致しないことがある点は、特に注意してください。
イベントが発生したときのより詳細な状況を特定する必要がある場合は、イベントハンドラに渡されるEventオブジェクトを参照してください。 イベントの種類によっては、イベントオブジェクトに追加情報が格納されている事があります。
非同期イベントに対するイベントハンドラの実行で、ここで説明したような実行タイミングによる影響を抑止するためには、 必ずイベントオブジェクトの付加情報を参照して処理するようにしてください。
イベントの順序性¶
同期イベントでは、イベントは、イベント発生の瞬間にイベントハンドラに渡されます。
非同期イベントであれば、イベントは、イベントを発生させた動作と同じ順序でイベントキューに格納されます。
また、イベントキューに格納されたイベントは、同じ順序で取り出されてイベントハンドラに渡されます。
これらの順序は、常に一定です。
しかし、イベントを発生させる動作がいつも同じ順序で行われる保証はありません。
例えば、LostFocusイベントの次に、別のオブジェクトのGetFocusイベントが必ず発生するという前提は誤りです。 また、画面の操作により発生するイベントと、CRSスクリプトで発行したイベントのどちらが先になるのかも状況により変わるため、特定の発生順序を前提とした処理は誤りです。
例えば、Buttonオブジェクトを押下したとき発生する可能性のあるイベントは、GetFocusとTouchイベントです。
しかし、はじめからButtonにフォーカスがあるときGetFocusは発生しません。 また、onGetFocusイベントハンドラ内で、ユーザ定義イベントを発行したとき、Touchイベントとユーザ定義イベントのどちらが先にイベントキューに格納されるかは不定です。 これは、Touchイベントの発生要因となる、マウスボタンを離す操作と、CRSスクリプトの実行でpostEventメソッドを実行する処理で、 どちらが先に行われるかを決定する事ができないためです。
イベントハンドラは、どのような順序でイベントが発生しても、正しい動作となるように考慮する必要があります。
イベントの発生順序に依存する必要がある場合、そのイベントを発行する要因が、常に同じ順序で発生することを検証してください。
ただし、Biz/Browserに内蔵されるすべてのクラスは、複数のイベントの発生順序を保障していないため、 CRSスクリプトで発行するユーザ定義イベントのみ、発生順序が保障される可能性があります。
同期イベントと非同期イベントの分類¶
組み込みクラスのイベントには、同期(send)または非同期(post)のイベントモデルが定義されています。
現行の Biz/Browser DT で、非同期イベントとして定義されているイベントは次のとおりです。
イベント名 |
発生元クラス |
イベントモデル |
|---|---|---|
|
ChartBarSeries、ChartBoxSeries、ChartLineSeries、ChartPercentBarSeries、ChartPieSeries、ChartScatterSeries、ChartSplineSeries、ChartStackedBarSeries、ChartStandardBarSeries、ChartXYSeries |
非同期( |
|
Task、AsyncTask |
非同期( |
|
Task、AsyncTask |
非同期( |
|
Root |
非同期( |
|
Root |
非同期( |
上表以外の組み込みクラスのイベントの多くは、イベント仕様上は同期(send)イベントです。
例えば、ネイティブモードでの Touch、Pressed、Released、Clicked、MouseEnter、
MouseLeave、Timer、SelectionChanged、EditChanged などが該当します。
イベント名が似ている場合でも、発生元クラスのイベント一覧で分類を確認してください。
この分類は、組み込みクラスのイベント仕様に定義されたモデルを示します。 実際の処理モデルは、イベントを発行する処理や互換モードによって変わる場合があります。 例えば、次のイベントはイベント仕様上のモデルと発行経路が異なります。
イベント |
非同期になる条件 |
|---|---|
|
ソケット受信処理がイベントキューへ登録して発行します。 |
|
セッション終了処理がイベントキューへ登録して発行します。 |
|
互換モードでは、発行側の実装によりイベントキューへ登録される場合があります。 |
このため、イベント名だけで実行時の処理モデルを常に決められるわけではありません。
CRSからイベントを発行する場合は、postEvent の第2引数で明示的に指定できます。
postEvent(ev, true)は同期イベントとして直ちに処理します。postEvent(ev, false)は非同期イベントとしてイベントキューに登録します。第2引数を省略した場合、通常モードでは同期、互換モードでは非同期として処理します。
イベントハンドラ内で
postEvent()を引数なしで呼び出した場合は、処理中のイベントモデルを引き継いで親オブジェクトへ転送します。
したがって、ユーザ定義イベントを必ず非同期で処理する場合は、
postEvent(new Event("イベント名"), false) のように第2引数へ false を指定してください。