事件管理器

EventManagerBase 是一个抽象类,旨在通过 Widget 类的 on_motion() 方法,将运动事件(MotionEvent 的实例)分发给各个控件。

警告

此功能目前仍处于实验阶段,只要此警告存在,该状态将持续。

Manager 是窗口与其控件之间的一个层。WindowBase 会将其在 on_motion() 方法中接收到的所有事件转发给所有声明接收这些事件类型的管理器。即使其中一个管理器接受了事件(通过返回 True),事件仍会继续遍历管理器列表。

何时使用事件管理器

当你想要实现以下功能时,请使用管理器:

  • 通过 on_motion() 方法将触摸、悬停、键盘、摇杆或其他任何事件分发给各个控件。

  • 按任意条件分发过滤后的运动事件,例如通过 deviceprofile

  • 将多个运动事件(如触摸、悬停等)合并为一个新事件,并将其分发给各个部件。

  • 分发一次性通用事件,如应用暂停/恢复。

  • 编写一个事件模拟器,类似于触摸模拟器,在窗口的画布上为每次模拟的触摸绘制一个圆形。

定义并注册事件管理器

  1. 继承 EventManagerBase,并通过在 EventManagerBase.type_ids 属性中声明事件类型来设置该管理器应接收哪些事件。

  2. 实现 EventManagerBase.dispatch() 方法,该方法将由窗口调用,以传递事件类型("begin"、"update"、"end" 之一)和一个事件。

  3. 实现 EventManagerBase.start()EventManagerBase.stop(),以便在需要时分配和释放额外资源。

  4. 使用 register_event_manager() 方法向窗口注册一个管理器实例。这可以通过重写 build()on_start() 方法来实现。

所有已注册的管理器都保存在 event_managers 列表中。要注销一个管理器,请调用 unregister_event_manager() 方法,该方法本身可以在 on_stop() 方法中调用。

向组件分发事件

注册后,窗口将启动管理器,并将所有在 EventManagerBase.type_ids 中声明的事件类型转发给管理器的 EventManagerBase.dispatch() 方法。如何分发这些事件由管理器决定,既可以通过遍历 EventManagerBase.window.children 列表并分发 on_motion 事件,也可以采用其他不同的逻辑。如果事件支持抓取功能(参见 grab()ungrab() 方法),那么抓取事件的分发同样由管理器负责。

管理器可以通过更改 dispatch_mode 属性的值,为事件分配不同的分发模式,以决定事件如何在控件树中分发。在更改模式之前,管理器应存储/恢复当前模式,可以通过使用局部变量或使用事件的 push() / pop() 方法来实现。

目前,在 Widget 类中,on_motion 方法识别三种调度模式(行为):

  1. 默认分发(需要 MODE_DEFAULT_DISPATCH)——事件将遍历 widget 的 children 列表,从列表中的第一个 widget 开始,直到事件被接受或到达为该事件注册的最后一个 widget。模式 MODE_DEFAULT_DISPATCHMotionEvent 类中默认分配。

  2. 过滤分发(需要 MODE_FILTERED_DISPATCH)——事件将仅通过已注册的子部件进行传递。

  3. 不向子组件分发(需要 MODE_DONT_DISPATCH)——事件将不会分发到子部件。

请注意,窗口没有 motion_filter 属性,因此其 children 列表中不包含已过滤的控件列表。

class kivy.eventmanager.EventManagerBase[源代码]

基类:object

抽象类,包含 start()stop()dispatch() 方法,供特定类实现。

管理器接收触摸和悬停事件的示例:

class TouchHoverManager(EventManagerBase):

    type_ids = ('touch', 'hover')

    def start(self):
        # Create additional resources, bind callbacks to self.window

    def dispatch(self, etype, me):
        if me.type_id == 'touch':
            # Handle touch event
        elif me.type_id == 'hover'
            # Handle hover event

    def stop(self):
        # Release resources
dispatch(etype, me)[源代码]

将事件 me 分发给 window 中的控件。

参数:
etypestr

"begin"、"update" 或 "end" 中的一个

me: MotionEvent

当前正在分发的运动事件。

返回:

bool 值为 True 时停止事件分发。

在 2.1.0 版本加入.

start()[源代码]

启动管理器,将回调绑定到对象并创建额外资源。当调用此方法时,属性 window 会被赋值。

在 2.1.0 版本加入.

stop()[源代码]

停止管理器,解除与任何对象的绑定,并释放所有已分配的资源。

在 2.1.0 版本加入.

type_ids = None

覆盖此属性以声明管理器希望接收的事件类型ID。该属性将被 WindowBase 用于确定哪些事件应传递给 dispatch() 方法。

在 2.1.0 版本加入.

window = None

保存 WindowBase 的实例。

在 2.1.0 版本加入.

kivy.eventmanager.MODE_DEFAULT_DISPATCH = 'default'

将此模式分配给事件分发,使其通过控件的`children`列表进行,从列表中的第一个控件开始,直到事件被接受或到达为该事件注册的最后一个控件。最后一个已注册控件之后的控件将被忽略。

在 2.1.0 版本加入.

kivy.eventmanager.MODE_DONT_DISPATCH = 'none'

将此模式分配给该事件,以防止事件分派到子部件。

在 2.1.0 版本加入.

kivy.eventmanager.MODE_FILTERED_DISPATCH = 'filtered'

将此模式设置为仅将事件分发给先前注册接收相同 type_id 类型事件的子部件,而非所有子部件。

在 2.1.0 版本加入.