The UI Toolkit event system listens to events, coming from the operating system or scripts, and dispatches these events to visual elements using the EventDispatcher
. The event dispatcher determines an appropriate dispatching strategy for each event it sends. Once determined, the dispatcher executes the strategy.
视觉元素和其他支持类实现了几个事件的默认行为。有时,涉及创建和发送额外的事件。例如,MouseMoveEvent
可能生成额外的 MouseEnterEvent
和 MouseLeaveEvent
。这些额外的事件将放置在队列中,并会在当前事件完成后处理这些事件。例如,完成 MouseMoveEvent
后处理 MouseEnterEvent
和 MouseLeaveEvent
事件。
EventDispatcher.DispatchEvent()
的首个任务是查找事件目标。
有时,这很容易,因为已经设置事件 target
属性。但是,对于源自操作系统的大多数事件,则并非如此。
事件的目标取决于事件类型。对于鼠标事件,目标通常是直接位于鼠标下面最上层的可选择元素。对于键盘事件,目标是当前聚焦的元素。
找到目标后,目标会存储在 EventBase.target
中,且在分发过程中不会改变。属性 Event.currentTarget
会更新为当前正在处理该事件的元素。
大多数鼠标事件使用拾取模式来确定其目标。VisualElement
类有一个支持以下值的 pickingMode
属性:
PickingMode.Position
(默认值):根据位置矩形执行拾取。PickingMode.Ignore
:阻止因鼠标事件而拾取。可以覆盖 VisualElement.ContainsPoint()
方法来执行自定义的交集逻辑。
有时,在鼠标按下后,元素必须捕获鼠标位置以确保所有后续的鼠标事件都只发送给自己(即使指针不再悬停在该元素上)。如果一个控件会响应鼠标按下和鼠标松开序列 - 在鼠标按下和鼠标松开事件之间可能会移动鼠标,通常便会有此要求。例如,在单击按钮、滑动条或滚动条时就属于这种情况。
要捕获鼠标,请调用 element.CaptureMouse()
或 MouseCaptureController.CaptureMouse()
。
要释放鼠标,请调用 MouseCaptureController.ReleaseMouse()
。如果在调用 CaptureMouse()
时已经有另一个元素正在捕获鼠标,该元素将收到 MouseCaptureOutEvent
并失去此捕获。
在应用程序中,任何时候都只能有一个元素具有捕获。当元素具有捕获时,该元素便是除鼠标滚轮事件之外的所有后续鼠标事件的目标。
注意:这只适用于尚未设置目标的鼠标事件。
每个 UIElement 面板都有一个焦点环用于定义元素的焦点顺序。默认情况下,元素的焦点顺序是通过对视觉元素树执行深度优先搜索 (DFS) 来确定的。例如,以下所示的树的焦点顺序将是 F、B、A、D、C、E、G、I、H。
有些事件使用焦点顺序来确定哪个元素获得焦点。例如,键盘事件的目标是当前获得焦点的元素。
使用 focusable
属性可控制元素的可聚焦性。默认情况下,无法聚焦 VisualElements
,但是默认可聚焦某些子类(例如 TextField
)。
使用 tabIndex
属性可按如下方式控制焦点顺序(tabIndex
默认值为 0):
tabIndex
为负,则无法用 Tab 键导航该元素。tabIndex
为零,该元素保持默认的 Tab 顺序(通过焦点环算法确定的顺序)。tabIndex
为正,该元素将置于 tabIndex
为零 (tabIndex = 0
) 或具有更高 tabIndex
的其他元素之前。选择事件目标后,分发程序将计算事件的传播路径。传播路径是接收事件的视觉元素的有序列表。
元素列表的获得方式是从视觉元素树的根开始,朝着目标往下,再朝着树的根往上。
传播路径的第一阶段从根下降到目标父级。此阶段称为涓滴 (trickle down) 阶段。
传播路径的最后一个阶段从目标父级上升到根。此阶段称为冒泡 (bubble-up) 阶段。
事件目标位于传播路径中间。
大多数事件类型将发送到传播路径上的所有元素。但是,一些事件类型会跳过冒泡阶段。此外,一些事件类型仅发送到事件目标。
如果元素被隐藏或禁用,它将不会接收事件。事件仍会传播到被隐藏或禁用的元素的祖先和后代。
在沿着传播路径发送事件时,Event.currentTarget
更新为当前正在处理事件的元素。这意味着,在事件回调函数中,Event.currentTarget
是对回调注册的元素,而 Event.target
是发生事件的元素。
每个事件类型都有自己的分发行为。下表以三列的形式汇总了每个事件类型的行为:
涓滴 | 冒泡 | 可取消 | |
---|---|---|---|
MouseCaptureOutEvent | ✔ | ✔ | |
MouseCaptureEvent | ✔ | ✔ | |
ChangeEvent | ✔ | ✔ | |
ValidateCommandEvent | ✔ | ✔ | ✔ |
ExecuteCommandEvent | ✔ | ✔ | ✔ |
DragExitedEvent | ✔ | ✔ | |
DragUpdatedEvent | ✔ | ✔ | ✔ |
DragPerformEvent | ✔ | ✔ | ✔ |
DragEnterEvent | ✔ | ||
DragLeaveEvent | ✔ | ||
FocusOutEvent | ✔ | ✔ | |
BlurEvent | ✔ | ||
FocusInEvent | ✔ | ✔ | |
FocusEvent | ✔ | ||
InputEvent | ✔ | ✔ | |
KeyDownEvent | ✔ | ✔ | ✔ |
KeyUpEvent | ✔ | ✔ | ✔ |
GeometryChangedEvent | |||
MouseDownEvent | ✔ | ✔ | ✔ |
MouseUpEvent | ✔ | ✔ | ✔ |
MouseMoveEvent | ✔ | ✔ | ✔ |
ContextClickEvent | ✔ | ✔ | ✔ |
WheelEvent | ✔ | ✔ | ✔ |
MouseEnterEvent | ✔ | ✔ | |
MouseLeaveEvent | ✔ | ✔ | |
MouseEnterWindowEvent | ✔ | ||
MouseLeaveWindowEvent | ✔ | ||
MouseOverEvent | ✔ | ✔ | ✔ |
MouseOutEvent | ✔ | ✔ | ✔ |
ContextualMenuPopulateEvent | ✔ | ✔ | ✔ |
AttachToPanelEvent | |||
DetachFromPanelEvent | |||
TooltipEvent | ✔ | ✔ | |
IMGUIEvent | ✔ | ✔ | ✔ |
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.