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_HANDLED ; EVENT_UNHANDLED 如果调用了一个或多个事件处理程序而没有返回任何事件处理程序 EVENT_HANDLED ;
False
如果没有注册任何事件处理程序。
- 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_handler , set_handlers 或
push_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()
用于接受的参数类型。