UI Toolkit のイベントは、HTML イベント に似ています。イベントが発生すると、ターゲットのビジュアル要素と、ビジュアル要素ツリー内の伝播パス内のすべての要素に送信されます。
イベント処理の流れは以下の通りです。
ExecuteDefaultActionAtTarget()
を呼び出します。ExecuteDefaultAction()
をイベントターゲット上で呼び出します。イベントが伝搬経路を移動すると、Event.currentTarget
プロパティは、現在そのイベントを処理する要素に更新されます。イベントコールバック関数内では、以下の通りです。
Event.currentTarget
は、コールバックが登録されるビジュアル要素です。Event.target
は、元のイベントが発生するビジュアル要素です。詳しくは、イベントのディスパッチ を参照してください。
イベントコールバックを登録して、テキストラベル上でマウスをクリックしたときの動作など、既存クラスの個々のインスタンスの動作をカスタマイズできます。
伝搬経路上の各要素 (ターゲットを除く) は、イベントを 2 回受け取ることができます。
デフォルトでは、登録されたコールバックは、ターゲットフェーズとバブルアップフェーズの間に実行されます。このデフォルトの動作により、親要素が子要素の後に反応するようになります。
一方、親要素を子要素より先に反応させたい場合は、TrickleDown.TrickleDown
オプションでコールバックを登録します。
using UnityEngine;
using UnityEngine.UIElements;
...
VisualElement myElement = new VisualElement();
// Register a callback for the trickle-down phase.
myElement.RegisterCallback<MouseDownEvent>(MyCallback, TrickleDown.TrickleDown);
...
これは、ディスパッチャーに、ターゲット段階と降下段階でコールバックを実行するように通知します。
カスタムビヘイビアを特定のビジュアル要素に加えるには、その要素にイベントコールバックを登録します。
例えば、以下のコードは MouseDownEvent
のコールバックを登録します。
// マウスダウンイベントのコールバックの登録event
myElement.RegisterCallback<MouseDownEvent>(MyCallback);
コールバック関数のシグネチャは以下のようになります。
void MyCallback(MouseDownEvent evt) { /* ... */ }
1 つのイベントに対して複数のコールバックを登録することができます。ただし、同じコールバック関数を登録できるのは、同じイベントと同じ伝播段階に 1 度だけです。
VisualElement
からコールバックを削除するには、myElement.UnregisterCallback()
メソッドを呼び出します。
イベントのコールバックと一緒にカスタムデータを送ることができます。カスタムデータを添付するには、呼び出しを拡張してコールバックを登録する必要があります。
以下の例では、MouseDownEvent
のコールバックを登録し、カスタムデータをコールバック関数に送信しています。
// ユーザーデータをコールバックとともに送信
myElement.RegisterCallback<MouseDownEvent, MyType>(MyCallbackWithData, myData);
コールバック関数のシグネチャは以下のようになります。
void MyCallbackWithData(MouseDownEvent evt, MyType data) { /* ... */ }
UI コントロールは、value
プロパティを使用して、以下の例のように内部状態のデータを保持することができます。
Toggle
は Toggle
がオンまたはオフになると変化するブール値を格納します。IntegerField
は、フィールドの値を保持する整数を格納します。コントロールの値は以下のようにして取得できます。
コントロールから直接値を取得します: int val = myIntegerField.value;
コントロールから送信される ChangeEvent
をリッスンし、変更が発生したときに処理を行います。以下のように、イベントに対するコールバックを登録する必要があります。
//RegisterValueChangedCallback is a shortcut for RegisterCallback<ChangeEvent>.
//It constrains the right type of T for any VisualElement that implements an
//INotifyValueChange interface.
myIntegerField.RegisterValueChangedCallback(OnIntegerFieldChange);
コールバック関数のシグネチャは以下のようになります。
void OnIntegerFieldChange(ChangeEvent<int> evt) { /* ... */ }
コントロールの値を以下のようにして変更できます。
value
変数を直接変更します。myControl.value = myNewValue;
これは新しいChangeEvent
をトリガーします。myControl.SetValueWithoutNotify(myNewValue);
を使用します。これは新しいChangeEvent
をトリガーしません。詳しくは、イベントの変更 を参照してください。
ポインターの入力を処理する場合、コントロールにポインターをキャプチャさせたい場合があります。ビジュアル要素がポインターをキャプチャすると、ポインターがビジュアル要素上にあるかどうかにかかわらず、Unity はポインターに関連するすべてのイベントをビジュアル要素に送信します。例えば、ドラッグイベントを受信するコントロールを作成し、ポインターをキャプチャすると、コントロールはポインターの位置に関係なくドラッグイベントを受信します。
ポインターをキャプチャするには、キャプチャイベント を使用します。例は、カスタムエディターウィンドウ内にドラッグアンドドロップ UI を作成する を参照してください。
カスタムコントロールを実装している場合、UI Toolkit のイベントに 2 つの方法で応答することができます。
イベントに対してどのように対応するかは、状況によって異なります。
コールバックとデフォルトアクションの違いは以下の通りです。
デフォルトアクションは、クラスのすべてのインスタンスに適用されます。デフォルトアクションを実装するクラスは、そのインスタンスにコールバックを登録することもできます。
クラスにデフォルトのアクションを実装する場合、VisualElement
の新しいサブクラスを派生させ、ExecuteDefaultActionAtTarget()
メソッドか ExecuteDefaultAction()
メソッドのいずれか、または両方を実装する必要があります。
デフォルトアクションは、ビジュアル要素のサブクラスのインスタンスがイベントを受け取ったときに、各インスタンス上で実行されます。デフォルトアクションをカスタマイズするには、以下の例のように、 ExecuteDefaultActionAtTarget()
と ExecuteDefaultAction()
をオーバーライドします。
override void ExecuteDefaultActionAtTarget(EventBase evt)
{
// Call the base function.
base.ExecuteDefaultActionAtTarget(evt);
if (evt.eventTypeId == MouseDownEvent.TypeId())
{
// ...
}
else if (evt.eventTypeId == MouseUpEvent.TypeId())
{
// ...
}
// More event types
}
ExecuteDefaultAction()
にデフォルトアクションを実装すると、デフォルトのアクションの実行を停止または防止できます。
ターゲットのデフォルトアクションを親のコールバックの前に実行したい場合は、デフォルトアクションを ExecuteDefaultActionAtTarget()
に実装します。
デフォルトアクションは、あるタイプの要素がイベントを受け取ったときの動作と考える必要があります。例えば、チェックボックスは、クリックイベントに反応して、その状態を切り替えます。これを実行するには、すべてのチェックボックスにコールバックを登録するのではなく、デフォルトアクションの仮想関数をオーバーライドします。
以下は、カスタムコントロールの効率的な実践例です。
要素の動作をデフォルトの動作で実装する必要があります。インスタンスに接続されたコールバックで PreventDefault()
を呼び出すことで、要素のデフォルトの動作をキャンセルすることができます。
動作をデフォルトアクションとして実装することによるその他の利点は以下の通りです。
柔軟性を高めるために、イベントのディスパッチ処理中にイベントターゲットのデフォルトのアクションを 2 か所で実行できます。
ExecuteDefaultActionsAtTarget()
をオーバーライドします。ExecuteDefaultActions()
をオーバーライドします。可能であれば ExecuteDefaultActions()
にクラスのデフォルトアクションを実装してください。これにより、クラスをオーバーライドするためのオプションが増えます。PreventDefault()
を呼び出して、イベント伝播プロセスの降下段階または上昇段階でクラスをオーバーライドすることができます。
イベントが親要素に伝搬してはいけない場合は、デフォルトアクション中にイベントの伝搬を停止する必要があります。例えば、テキストフィールドは KeyDownEvent
を受け取って、その値を変更します。例えば、Delete
キーでコンテンツを削除するように。このイベントは、親のビジュアル要素に伝播してはいけません。ExecuteDefaultActionsAtTarget()
を使ってデフォルトアクションを実装し、StopPropagation()
を呼び出して上昇段階でイベントが処理されないようにします。
デフォルトアクションは、イベントターゲットに対してのみ実行されます。クラスが子要素や親要素を対象としたイベントに反応するには、降下または上昇の伝搬段階で、イベントを受け取るコールバックを登録する必要があります。パフォーマンスを向上させるために、クラスにコールバックを登録することは避けてください。
コールバックやデフォルトアクションの中でイベントを処理する場合、イベントの伝搬やデフォルトアクションの実行を停止することができます。例えば、親パネルは降下段階で伝搬を停止し、子パネルがイベントを受け取らないようにすることができます。
EventBase.PreDispatch()
と EventBase.PostDispatch()
メソッドの実行は、イベントクラスの内部で防ぐことはできません。
以下のメソッドは、イベント伝播とデフォルトアクションに影響します。
StopImmediatePropagation()
: イベントの伝搬プロセスを直ちに停止します。そのため、そのイベントに対する他のコールバックは実行されません。ただし、ExecuteDefaultActionAtTarget()
と ExecuteDefaultAction()
のデフォルトアクションは引き続き実行されます。StopPropagation()
: 現在の要素の最後のコールバック後のイベント伝播プロセスを停止します。これにより、現在の要素のすべてのコールバックが確実に実行されますが、それ以降の要素はイベントに反応しません。ExecuteDefaultActionAtTarget()
と ExecuteDefaultAction()
のデフォルトアクションだけは引き続き実行されます。PreventDefault()
: Prevents the event propagation process from calling the ExecuteDefaultActionAtTarget()
and ExecuteDefaultAction()
default actions. PreventDefault()
doesn’t prevent the execution of other callbacks and doesn’t affect the ExecuteDefaultActionAtTarget()
action during the bubble-up phase.