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: str, *args: Any) bool | None

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

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

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

返回类型:

bool | None

返回:

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

event(*args: Any) Callable

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

如果函数或方法名称与事件名称匹配,则可以在没有参数的情况下添加装饰器。同样,如果名称不匹配,您可以通过将其作为参数传递来提供目标事件名称。

姓名匹配::

win = window.Window()

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

名称不匹配::

@win.event('on_resize')
def foo(self, width, height):
    # ...
返回类型:

Callable

pop_handlers() None

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

返回类型:

None

push_handlers(*args: Any, **kwargs: Any) None

将新级别推入处理程序堆栈,并添加0个或更多处理程序。

此方法首先将新级别推入处理程序堆栈的顶部。然后,它附加传递到这个新级别的任何处理程序。

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

返回类型:

None

classmethod register_event_type(name: str) str

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

在派遣事件之前,必须首先按名称注册它们。注册事件类型允许调度程序在附加事件处理程序名称时对其进行验证,并在附加对象中搜索合适的处理程序。

返回类型:

str

remove_handler(name: str, handler: Callable) None

删除单个事件处理程序。

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

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

返回类型:

None

remove_handlers(*args: Any, **kwargs: Any) None

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

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

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

返回类型:

None

set_handler(name: str, handler: Callable) None

附加单个事件处理程序。

返回类型:

None

set_handlers(*args: Any, **kwargs: Any) None

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

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

返回类型:

None

event_types: list