pyglet.event

事件调度框架。

在Piglet中生成事件的所有对象都实现 EventDispatcher ,为注册和操作事件处理程序提供一致的接口。一个常用的事件调度程序是 pyglet.window.Window

事件类型

对于每个事件调度程序,都有一组它调度的事件;这些事件对应于您可以附加的事件处理程序的类型。事件类型由它们的名称标识,例如‘’ON_RESIZE‘’。如果您要创建一个新类来实现 EventDispatcher ,你必须打电话给 EventDispatcher.register_event_type 对于每种事件类型。

附加事件处理程序

事件处理程序只是一个函数或方法。您可以通过在实例上设置适当的函数来附加事件处理程序::

def on_resize(width, height):
    # ...
dispatcher.on_resize = on_resize

还有一个方便的装饰符,可以减少打字:

@dispatcher.event
def on_resize(width, height):
    # ...

您可能更喜欢子类化并覆盖事件处理程序::

class MyDispatcher(DispatcherClass):
    def on_resize(self, width, height):
        # ...

事件处理程序堆栈

当使用上述方法将事件处理程序附加到调度程序时,它将替换任何现有的处理程序(导致不再调用原始处理程序)。每个调度程序都维护一个事件处理程序堆栈,允许您在现有事件处理程序的“上方”插入一个事件处理程序,而不是替换它。

“推送”事件处理程序有两个主要用例:

  • 临时拦截来自调度程序的事件,方法是将一组定制的处理程序推送到调度程序上,然后在稍后将它们同时“弹出”。

  • 创建事件处理程序的“链”,其中事件从最顶部(最近添加的)处理程序传播到底部,直到处理程序处理它。

使用 EventDispatcher.push_handlers 若要在堆栈中创建新级别并向其附加处理程序,请执行以下操作。您可以同时推送多个处理程序::

dispatcher.push_handlers(on_resize, on_key_press)

如果函数处理程序与其处理的事件具有不同的名称,请使用关键字参数::

dispatcher.push_handlers(on_resize=my_resize, on_key_press=my_key_press)

事件处理程序处理完事件后,该事件将传递给倒数第二个的事件处理程序,除非该处理程序返回 EVENT_HANDLED 这会阻止进一步的传播。

要删除顶层堆栈级别上的所有处理程序,请使用 EventDispatcher.pop_handlers

请注意,推送到堆栈上的任何处理程序优先于直接在实例上设置的处理程序(例如,使用上一节中描述的方法),无论它们是在何时设置的。例如,处理程序 foo 在处理程序之前调用 bar 在以下示例中:

dispatcher.push_handlers(on_resize=foo)
dispatcher.on_resize = bar

调度事件

Pyglet对所有应用程序代码使用单线程模型。事件处理程序仅在调用EventDispatcher.调度_事件`时才会被调用。

由特定的事件调度程序对相关事件进行排队,直到可以调度它们,此时将按照最初生成事件的顺序调用处理程序。

这意味着您的应用程序使用主循环运行,该主循环不断更新应用程序状态并检查新事件:

while True:
    dispatcher.dispatch_events()
    # ... additional per-frame processing

并非所有事件调度程序都需要调用 dispatch_events ;查看特定的类文档。

备注

为了防止垃圾回收问题, EventDispatcher 类只包含对推送事件处理程序的弱引用。这意味着下面的示例将不起作用,因为推送的对象将落入作用域并被收集:

dispatcher.push_handlers(MyHandlerClass())

相反,您必须确保在推送对象之前保留对该对象的引用。例如::

my_handler_instance = MyHandlerClass()
dispatcher.push_handlers(my_handler_instance)
exception EventException

无法附加事件处理程序时引发异常。

class EventDispatcher

通用事件调度程序接口。

有关用法,请参阅模块文档字符串。

dispatch_event(event_type, *args)

将事件调度到附加的事件处理程序。

该事件被传播到堆栈中所有已注册的事件处理程序,从开始到顶部再向下传播。如果任何注册的事件处理程序返回 EVENT_HANDLED ,则堆栈下面的其他处理程序都不会收到此事件。

此方法有几个可能的返回值。如果任何事件处理程序已返回 EVENT_HANDLED ,则此方法也将返回 EVENT_HANDLED 。如果不是,此方法将返回 EVENT_UNHANDLED 。如果没有注册接收该事件的事件, False 是返回的。

参数:
event_type应力

要调度的事件的名称。

args序列

要传递给事件处理程序的可选参数。

返回类型:

bool or None

返回:

EVENT_HANDLED 如果返回任何事件处理程序 EVENT_HANDLEDEVENT_UNHANDLED 如果调用了一个或多个事件处理程序而没有返回任何事件处理程序 EVENT_HANDLEDFalse 如果没有注册任何事件处理程序。

event(*args)

事件处理程序的函数修饰器。

用法::

win = window.Window()

@win.event
def on_resize(self, width, height):
    # ...

或:

@win.event('on_resize')
def foo(self, width, height):
    # ...
pop_handlers()

从堆栈中弹出顶级事件处理程序。

push_handlers(*args, **kwargs)

将一个级别推到处理程序堆栈的顶部,然后附加零个或多个事件处理程序。

如果给定了关键字参数,它们将命名要附加的事件类型。否则,可调用对象的 __name__ 属性将被使用。还可以指定任何其他对象,在这种情况下,将搜索具有事件名称的可调用对象。

classmethod register_event_type(name)

向调度程序注册事件类型。

注册事件类型允许调度程序在附加事件处理程序时验证它们的名称,并在附加的对象中搜索合适的处理程序。

参数:
name应力

要注册的事件的名称。

remove_handler(name, handler)

删除单个事件处理程序。

给定的事件处理程序将从它出现的第一个处理程序堆栈帧中移除。处理程序必须与传递给的处理程序完全相同 set_handlerset_handlerspush_handlers() ;并且名称必须与其绑定到的事件类型匹配。

如果未设置事件处理程序,则不会引发错误。

参数:
name应力

要删除的事件类型的名称。

handler可召回

要移除的事件处理程序。

remove_handlers(*args, **kwargs)

从事件堆栈中移除事件处理程序。

看见 push_handlers() 用于接受的参数类型。从包含任何给定处理程序的第一个堆栈帧中移除所有处理程序。如果没有任何处理程序出现在该帧中,或者如果没有堆栈帧包含任何给定的处理程序,则不会引发错误。

如果移除处理程序后堆栈帧为空,则会将其从堆栈中移除。请注意,这会干扰预期的对称性 push_handlers()pop_handlers()

set_handler(name, handler)

附加单个事件处理程序。

参数:
name应力

要附加到的事件类型的名称。

handler可召回

要附加的事件处理程序。

set_handlers(*args, **kwargs)

将一个或多个事件处理程序附加到处理程序堆栈的顶层。

看见 push_handlers() 用于接受的参数类型。