一个面板表示一个 UI 层级结构的可见实例。它处理视觉树层级结构内的元素行为事件分发。它具有对层级结构的根视觉元素的引用。对于运行时 UI,它可以与 UGUI 中的 Canvas 相媲美。
您必须将视觉元素的实例附加到面板,才能使其生成或接收事件。
当视觉元素与面板的关系发生变化时,面板事件会在该视觉元素上触发。例如,当您将视觉元素添加到面板 (AttachToPanelEvent
) 或从面板中分离时 (DetachFromPanelEvent
) 。
面板事件仅在发生面板更改时发送到层级结构中直接受影响的视觉元素及其后代。向面板附加或从面板分离后代视觉元素时,父元素不会接收事件。
例如,在下面的 UXML 代码中,当您将 parent
视觉元素添加到已经附加到面板的层级结构时,parent
、child
和 grandchild
都会收到同一事件。如果您从同一 UXML 层级结构中分离 parent
,所有视觉元素都会收到 DetachFromPanel
事件。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:VisualElement name="parent">
<ui:VisualElement name="child">
<ui:VisualElement name="grandchild" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
所有面板事件的基类是 PanelChangedEventBase。
事件 | 描述 | 涓滴 | 冒泡 | 可取消 |
---|---|---|---|---|
AttachToPanelEvent | 在元素(或其父元素之一)附加到面板后立即发送。 | |||
DetachFromPanelEvent | 在元素(或其父元素之一)即将从面板分离时发送。 |
originPanel
:originPanel
包含特定于 DetachFromPanelEvent
的数据。它包含在面板更改期间视觉元素从中分离的源面板。
destinationPanel
:destinationPanel
包含特定于 AttachFromPanelEvent
的数据。它提供了视觉元素当前附加到的面板。
The following list provides the name, description, and target of each event in the event family.
AttachToPanelEvent
在视觉元素附加到面板后触发。当您将视觉元素添加到附加到面板的层级结构时,也会发生这种情况。
target
:附加到面板的视觉元素。
The DetachFromPanelEvent
triggers before you remove a visual elementA node of a visual tree that instantiates or derives from the C# VisualElement
class. You can style the look, define the behaviour, and display it on screen as part of the UI. More info
See in Glossary from a panel. It also occurs when you remove a visual element from a hierarchy that’s attached to a panel.
target
:从面板分离的视觉元素。
下面的示例创建一个带有按钮的编辑器窗口,该按钮将向窗口添加附加标签。单击标签将再次删除它们。
此示例实现了一个自定义标签类,每当 VisualElement 的实例附加到面板或从面板分离时,该标签类都会向控制台打印一条消息。该示例重点演示 AttachToPanelEvent 和 DetachFromPanelEvent 事件的行为以及如何使用 originPanel 和 destinationPanel 属性。
要查看示例运行效果,请执行以下操作:
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
public class PanelEventsTestWindow : EditorWindow
{
[MenuItem("Window/UI Toolkit/Panel Events Test Window")]
public static void ShowExample()
{
PanelEventsTestWindow wnd = GetWindow<PanelEventsTestWindow>();
wnd.titleContent = new GUIContent("Panel Events Test Window");
}
public void CreateGUI()
{
// 为面板设置名称
rootVisualElement.panel.visualTree.name = "Our Window Root Visual Element";
// 添加一个按钮,它将向窗口添加自定义标签的新实例
rootVisualElement.Add(new Button(() => rootVisualElement.Add(new CustomLabel())) { text = "Add New Label" });
}
}
/// <summary>
/// 自定义标签类,在附加或分离时打印控制台消息。
/// </summary>
public class CustomLabel : Label
{
private static int m_InstanceCounter = 0;
private int m_LabelNumber;
public CustomLabel() : base()
{
m_LabelNumber = ++m_InstanceCounter;
text = $"Label #{m_LabelNumber} - click me to detach";
RegisterCallback<AttachToPanelEvent>(evt =>
{
Debug.Log($"I am label {m_LabelNumber} and I " +
$"just got attached to panel '{evt.destinationPanel.visualTree.name}'");
});
RegisterCallback<DetachFromPanelEvent>(evt =>
{
Debug.Log($"I am label {m_LabelNumber} and I " +
$"just got detached from panel '{evt.originPanel.visualTree.name}'");
});
// 注册一个 pointer down 回调,从层级结构中删除这个元素
RegisterCallback<PointerDownEvent>(evt => this.RemoveFromHierarchy());
}
}