ue3dUIToolkit中的事件传播机制和处理方法

UIToolkit中的事件传播机制和处理方法

分类:
ue3d - UIToolkit中的事件传播机制和处理方法

此文介绍UI Toolkit中事件传播的机制和处理方法,目的是了解Unity此类按钮实现背后的事件机制。

简单介绍

在UI Toolkit中,鼠标键盘输入等事件称为事件,按钮等交互式UI就是通过处理这个事件来制作的。

首先,创建一个EditorWindow,如下所示。

一个绿色的子元素(Child)放在红色的根元素(Root)下面,一个蓝色的元素(Grandchild)作为子元素放置。

ue3d - UIToolkit中的事件传播机制和处理方法

也可以使用UXML或者USS来组装,不过这次是代码,代码如下:

use UnityEditor;
use UnityEngine;
use UnityEngine.UIElements;

public seal class EventExample : EditorWindow
{
    private void OnEnable()
    {
        var root = rootVisualElement;
        root.style.paddingTop =  10 ;
        root.style.paddingBottom =  10 ;
        root.style.paddingLeft =  10 ;
        root.style.paddingRight =  10 ;
        root.style.backgroundColor =  new StyleColor( new Color( 0.8f , 0.3f , 0.3f ));

        var child =  new visual elements
        {
            style=
            {
                fill top=  10 ,
                fill bottom=  10 ,
                fill left=  10 ,
                fill right=  10 ,
                height =  new StyleLength(Length.Percent( 100 )),
                backgroundColor =  new StyleColor( new Color( 0.3f , 0.8f , 0.3f ))
            }
        };

        var grandchild = new VisualElement
        {
            style=
            {
                fill top=  10 ,
                fill bottom=  10 ,
                fill left=  10 ,
                fill right=  10 ,
                height =  new StyleLength(Length.Percent( 100 )),
                backgroundColor =  new StyleColor( new Color( 0.3f , 0.3f , 0.8f ))
            }
        };

        child. add (grandson);
        root. add(child);
    }

    [MenuItem( "Window/EventExample" )]
     public  static  void ShowWindow()
    {
        GetWindow<EventExample>( "EventExample" );
    }
}

注册事件回调

接下来,当鼠标在元素上按下时,为上一节中创建的子元素注册一个回调,要注册回调,请使用 ,指定要接收的事件类型。

grandchild.RegisterCallback<MouseDownEvent>(x =>
{
    Debug.Log( "mouse down on grandchild" );
});

当鼠标在元素上按下时,已经注册了一个事件,可以看到点击蓝色元素会输出日志。

接下来,为第一个父元素的红色元素以相同的方式注册一个鼠标按下事件。

child.RegisterCallback<MouseDownEvent>(x => 
{ 
    Debug.Log( $"mouse down on child" ); 
});

现在,如果在此状态下再次将鼠标按到蓝色元素上,将调用child两个事件回调。

ue3d - UIToolkit中的事件传播机制和处理方法

也就是说,如果按下第一个子元素,就可以看到父元素中的元素的事件也被调用了。

然而,在视觉上,只是点击了蓝色元素,所以想控制它只有蓝色元素(子)响应。如果想练习这种控制,需要准确了解事件传播在UI工具包中的工作原理。

事件传播的概念

在UI Toolkit中,当从操作系统接收到鼠标按下事件时,该事件首先发送到根可视化元素。然后它被传播给它的子对象,然后再传播给它的子对象。这样,事件从根元素传递到终端元素之前的元素的阶段称为涓流阶段。

ue3d - UIToolkit中的事件传播机制和处理方法

然后该事件被传播到终端元素(目标),这称为目标阶段。

目标不一定是终端元素,但在mousedown事件的上下文中它将是终端元素。

ue3d - UIToolkit中的事件传播机制和处理方法

最后,事件从终端元素之前的第一个元素传播到根元素,这称为起泡阶段。

ue3d - UIToolkit中的事件传播机制和处理方法

检查事件传播的行为

现在,可以在事件的回调中检索此事件传播信息,如下所示:

element.RegisterCallback<MouseDownEvent>(x => 
{ 
    x.propagationPhase; // propagation stage
    x.target; // target (terminal element) 
    x.currentTarget; // the element currently handling the event
});

因此,为了实现上述只想对视觉点击的元素做出反应,需要将事件传播阶段的感知过程改写如下:

grandchild.RegisterCallback<MouseDownEvent>(x => 
{ if (x.propagationPhase != PropagationPhase.AtTarget)
         return ; 
    Debug.Log( "mouse down on grandchild" ); 
}); 
child.RegisterCallback<MouseDownEvent>(x => 
{ if (x.propagationPhase != PropagationPhase.AtTarget)
         return ; 
    Debug.Log( "mouse down on child" ); 
});
    
    

现在,视觉上只有被点击的元素会做出反应。

另一方面,如上所述,对于目标元素以外的元素,事件将被处理两次:trickle-down phase和bubble-up phase。

RegisterCallback在该方法中,可以在第二个参数中指定要处理的阶段,默认情况下,它接收冒泡阶段事件,如果指定TrickleDown参数,它接收滴流阶段事件。

child.RegisterCallback<MouseDownEvent>(x => 
{ 
    Debug.Log( "mouse down on child" ); 
}, TrickleDown.TrickleDown);

停止事件的传播

还可以通过使用StopPropagation在中间停止事件传播

child.RegisterCallback<MouseDownEvent>(x => 
{ 
    Debug.Log( "Mouse down on child and stop propagation" ); 
    x.StopPropagation(); 
});

但是,在这种情况下,在同一时间注册的所有事件将按如下方式调用。

child.RegisterCallback<MouseDownEvent>(x =>
{
    Debug.Log("mouse down on child 1 and stop propagation");
    x.StopPropagation();
});
child.RegisterCallback<MouseDownEvent>(x =>
{
    Debug.Log("mouse down on child 2"); // This will be called even if you stop the propagation
});

如果不想调用同时注册的任何事件,请改用StopImmediatePropagation。

child.RegisterCallback<MouseDownEvent>(x =>
{
    Debug.Log("mouse down on child 1 and stop immediate propagation");
    x.StopImmediatePropagation(); // StopImmediatePropagation
});
child.RegisterCallback<MouseDownEvent>(x =>
{
    Debug.Log("mouse down on child 2"); // no longer called
});

打算在另一篇文章中写到它,但是即使以这种方式停止传播,仍然会执行定义为每个UI元素的默认操作的处理,PreventDefault用于避免默认操作处理。

child.RegisterCallback<MouseDownEvent>(x => 
{ 
    Debug.Log( "Mouse down on child and prevent default" ); 
    x.PreventDefault(); 
});

总结

至此,已经总结了事件在UI Toolkit中是如何工作的,以及如何注册回调注册来处理它们,
不过如果事件回调要处理的内容比较复杂,还有一个机制叫Manipulator,在下一篇文章中会介绍相关内容。

以上是关于UI Toolkit中的事件传播机制和处理方法的全部内容,如果你有任何反馈,请随时在本页面下方留言。

相关信息

  • 类型:知识
  • 字数:1034
  • 字符:5936
  • 适用软件:Unity
  • 说明:无
  • 编号:157416

热门内容

提示:3D天堂作为服务提供者,尊重网络版权及知识产权,对某些行为的发生不具备充分的监控能力,若无意间侵犯到您的权利,请 联系我们,我们会在收到信息后尽快给予处理。

本站文章版权归本站自创作者所有,未经允许不得转载!