Unity3D :处理事件

推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生

处理事件

UI 工具包中的事件类似于 HTML 事件 。 事件发生时,将沿着视觉元素树中的传播路径发送事件。 事件不仅发送到目标视觉元素,而且发送到传播路径中的所有元素。

事件处理顺序如下:

  1. 在从根元素往下到事件目标父级的元素上执行事件回调。 这是分发过程的涓滴阶段
  2. 在事件目标上执行事件回调。 这是分发过程的目标阶段
  3. 在事件目标上调用 。ExecuteDefaultActionAtTarget()
  4. 从事件目标父级往上到直到根部的元素上执行事件回调。 这是分发过程的冒泡阶段
  5. 在事件目标上调用 。ExecuteDefaultAction()

在沿着传播路径发送事件时, 属性更新为当前正在处理事件的元素。 在事件回调函数中:Event.currentTarget

  • Event.currentTarget 是回调注册的视觉元素。
  • Event.target 是原始事件发生的视觉元素。

有关更多信息,请参阅分发事件。

注册事件回调

通过注册事件回调,您可以自定义现有类的单个实例的行为,例如对鼠标单击文本标签做出反应。

传播路径上的每个元素(目标除外)对一个事件可以接收两次:

  • 在涓滴阶段一次。
  • 在冒泡阶段一次。

默认情况下,注册的回调会在目标阶段和冒泡阶段执行。 此默认行为可确保父元素在其子元素之后做出反应。 例如,如果您希望父元素在其子元素之前做出反应,请使用 选项注册回调:TrickleDown.TrickleDown

// 为涓滴阶段注册回调
myElement.RegisterCallback<MouseDownEvent>(MyCallback, TrickleDown.TrickleDown);

此代码将通知分发程序在目标阶段和涓滴阶段执行回调。

要将自定义行为添加到特定的视觉元素,您必须在该元素上注册事件回调。 例如,以下代码为 注册一个回调:MouseDownEvent

// 对鼠标按下事件注册回调
myElement.RegisterCallback<MouseDownEvent>(MyCallback);

回调签名应如下所示:

void MyCallback(MouseDownEvent evt) { /* ...*/ }

您可以为一个事件注册多个回调。 同一事件的同一回调函数在传播阶段只能注册一次。 要从 中移除回调,则调用 方法。VisualElementmyElement.UnregisterCallback()

将自定义数据发送到事件回调

您可以将自定义数据随同回调一起发送到事件。 要附加自定义数据,您必须通过扩展该调用的方式来注册回调。

以下代码为 注册一个回调并将自定义数据发送到回调函数:MouseDownEvent

//将用户数据一起发送到回调
myElement.RegisterCallback<MouseDownEvent, MyType>(MyCallbackWithData, myData);

回调函数应返回此签名:

void MyCallbackWithData(MouseDownEvent evt, MyType data) { /* ...*/ }

处理控件的输入事件

可以使用事件处理程序或使用操纵器来处理输入事件。

捕获指针

处理指针输入时,您可能希望控件捕获指针。当可视元素捕获指针时,Unity 将与指针关联的所有事件发送到可视元素,无论指针是否悬停在可视元素上。例如,如果创建一个接收拖动事件并捕获指针的控件,则无论指针位置如何,该控件仍会收到拖动事件。

若要捕获指针,请使用捕获事件。有关示例,请参阅在自定义编辑器窗口中创建拖放式 UI。

使用操纵器处理事件

如果要将事件逻辑与 UI 代码分开,请使用操纵器来处理事件。操纵器是存储、注册和注销事件回调的专用类。可以使用或继承 UI 工具包支持的操纵器之一来处理事件。

UI 工具包支持以下操纵器:

机械手继承自描述
Manipulator所有提供的机械手的基类。
KeyboardNavigationManipulatorManipulator使用键盘处理特定于设备的输入事件到更高级别的导航操作的转换。
MouseManipulatorManipulator处理鼠标输入。具有激活筛选器的列表。
ContextualMenuManipulatorMouseManipulator当用户单击鼠标右键或按键盘上的菜单键时显示上下文菜单。
PointerManipulatorMouseManipulator处理指针输入。具有激活筛选器的列表。
ClickablePointerManipulator跟踪元素上的鼠标事件,并在用户单击鼠标按钮时指针悬停在元素上时进行回调。

使用自定义控件响应事件

如果您要实现自定义控件,则可以通过两种方式响应 UI 工具包事件:

  • 注册事件回调。
  • 实现默认操作。

您选择如何响应事件取决于情况。

回调和默认操作之间的区别是:

  • 回调必须在类的实例上注册。 默认操作作为类上的虚拟函数运行。
  • 回调在传播路径上的所有视觉元素都会执行。 默认操作仅对事件目标执行。
  • 回调可能会执行额外的检查,以确定它们是否应该对事件做出反应。 例如,处理鼠标单击的回调可能会检查元素是否是事件的目标。 默认操作可以跳过此步骤。
  • 默认操作在性能上略有优势,因为它们在传播阶段不需要在回调注册表中查找。

实现默认操作

默认操作适用于该类的所有实例。 实现默认操作的类也可以在该类的实例上注册回调。

当一个类实现默认操作时,它必须派生一个新的 的子类并实现 和/或 方法,或两者都实现。VisualElementExecuteDefaultActionAtTarget()ExecuteDefaultAction()

默认操作是视觉元素子类的每个实例在接收事件时执行的操作。 您可以通过覆盖 和 来自定义默认操作,如下例所示:ExecuteDefaultActionAtTarget()ExecuteDefaultAction()

override void ExecuteDefaultActionAtTarget(EventBase evt)
{
    // 调用基函数。
    base.ExecuteDefaultActionAtTarget(evt);

    if (evt.GetEventTypeId() == MouseDownEvent.TypeId())
    {
        // ...
    }
    else if (evt.GetEventTypeId() == MouseUpEvent.TypeId())
    {
        // ...
    }
    //更多事件类型
}

通过在 中实现您的默认操作,您可以停止或阻止一个默认操作的执行。ExecuteDefaultAction()

如果希望在父级回调之前执行目标默认操作,请在 `ExecuteDefaultActionAtTarget() 中实现默认操作。

应该将默认操作视为一个元素类型在接收事件时应该具有的行为。 例如,复选框应通过切换其状态来响应单击事件。 您可以通过覆盖默认操作虚拟函数(而不是在所有复选框上注册回调)来实现此行为。

自定义控件的最佳实践

以下是自定义控件的最佳做法。

实现行为

您应该通过具有默认操作的元素来实现行为。 您可以在附加到实例的回调中调用 取消默认元素行为。PreventDefault()

将行为实现为默认操作的其他好处是:

  • 默认操作不需要在回调注册表中查找。
  • 没有回调的实例不进入传播过程。

为了获得更大灵活性,可在事件分发过程中的以下两个时刻执行事件目标的默认操作:

  1. 在涓滴与冒泡传播阶段之间,在刚执行目标回调之后,覆盖 。ExecuteDefaultActionsAtTarget()
  2. 在事件分发过程结束时,覆盖 。ExecuteDefaultActions()

类的默认操作

如有可能,尽量在 中实现类的默认操作。 这允许更多选项来覆盖类。 您可以在事件传播过程的涓滴阶段或冒泡阶段调用 来覆盖类。ExecuteDefaultActions()PreventDefault()

如果事件不应传播到父元素,则必须在默认操作期间停止事件传播。 例如,文本字段接收修改其值的 ,例如使用 键删除内容。 此事件不得传播到父视觉元素。 使用 实现默认操作并调用 以确保在冒泡阶段不处理该事件。KeyDownEventDeleteExecuteDefaultActionsAtTarget()StopPropagation()

仅对事件目标执行默认操作。 要使类对针对其子元素或父元素的事件做出反应,您必须注册回调以在涓流或冒泡传播阶段接收事件。 避免在类中注册回调以提高性能。

停止事件传播并取消默认操作

在回调或默认操作中处理事件时,您可以停止进一步的事件传播和默认操作的执行。 例如,父面板可通过在涓流阶段停止传播来阻止其子面板接收事件。

您不能阻止事件类自身内部的 和 方法。EventBase.PreDispatch()EventBase.PostDispatch()

以下方法影响事件传播和默认操作:

  • StopImmediatePropagation():立即停止事件传播过程,因此不会为事件执行其他回调。但是,和默认操作仍会执行。ExecuteDefaultActionAtTarget()ExecuteDefaultAction()
  • StopPropagation():在对当前元素进行最后一次回调后停止事件传播过程。这可确保所有回调都在当前元素上执行,但不会有其他元素对事件做出反应。和默认操作仍会执行。ExecuteDefaultActionAtTarget()ExecuteDefaultAction()
  • PreventDefaultAction():防止事件传播进程调用 和 默认操作。 不会阻止其他回调的执行,也不会在冒泡阶段使操作生效。ExecuteDefaultActionAtTarget()ExecuteDefaultAction()PreventDefaultAction()ExecuteDefaultActionAtTarget()

3D建模学习工作室整理翻译,转载请注明出处!

上一篇:Unity3D :调度事件 (mvrlink.com)

下一篇:Unity3D :合成和发送事件 (mvrlink.com)

NSDT场景编辑器 | NSDT 数字孪生 | GLTF在线编辑器 | 3D模型在线转换 | UnrealSynth虚幻合成数据生成器 | 3D模型自动纹理化工具
2023 power by nsdt©鄂ICP备2023000829号