应用程序事件循环

为了让Piglet处理鼠标和键盘事件等操作系统事件,应用程序需要进入应用程序事件循环。事件循环监视新事件,调度这些事件,然后休眠,直到需要执行其他操作。它还处理您在时钟上安排的任何功能(请参见 定期调用函数 )。Pyglet确保循环只重复完成所有预定功能和用户输入所需的次数。它在Windows、Linux和MacOS上针对性能和低功耗进行了很好的调整。

创建Windows并附加事件处理程序后,大多数应用程序只需调用::

pyglet.app.run()

这个 run() 函数直到所有打开的窗口都已关闭,或直到 pyglet.app.exit() 被称为。

一旦进入事件循环,它就会调度窗口事件(如键盘输入或鼠标移动)、来自控制器或操纵杆的事件以及发生的任何其他事件。默认情况下,应用程序事件循环还将刷新所有Windows并调度 on_draw() 事件的频率为60赫兹(每秒60次)。您可以通过将所需的间隔(以秒为单位)传递给 run() **

pyglet.app.run(1/30)    # 30Hz
# or
pyglet.app.run(1/120)   # 120Hz
# or for benchmarking, redraw as fast as possible:
pyglet.app.run(0)

传球 Nonerun() 是个特例。它将照常进入事件循环,但不会调度窗口事件。如果您希望不同窗口的刷新率不同,甚至希望在应用程序运行时更改刷新率,则可能需要这样做。

自定义事件循环

pyglet事件循环被封装在 EventLoop 类,该类提供了几个可被重写以自定义其行为的挂钩。建议仅对高级用户使用此功能--典型的应用程序和游戏不太可能需要此功能。

要使用 EventLoop 类,实例化它并调用 run **

event_loop = pyglet.app.EventLoop()
event_loop.run()

只有一个 EventLoop 可以一次运行;当 run() 方法称为模块变量 pyglet.app.event_loop 设置为正在运行的实例。其他pyglet模块,如 pyglet.window 就靠这个了。

事件循环事件

您可以侦听事件循环实例上的几个事件。其中一个有用的是 on_window_close() ,每当窗口关闭时都会调度。如果没有其他窗口,则此事件的默认处理程序退出事件循环。下面的示例覆盖此行为,以便在任何窗口关闭时退出应用程序:

event_loop = pyglet.app.EventLoop()

@event_loop.event
def on_window_close(window):
    event_loop.exit()
    return pyglet.event.EVENT_HANDLED

event_loop.run()

覆盖默认空闲策略

这个 pyglet.app.EventLoop.idle() 方法在事件循环的每次迭代中都会被调用。它负责调用调度的时钟函数,并决定应用程序的空闲程度。如果您对调整应用程序的性能有特定要求,则可以重写此方法;尤其是在它使用许多窗口的情况下。

默认实施具有以下算法:

  1. 打电话 pyglet.clock.tick() 使用 poll=True 调用任何计划的函数。

  2. 返回的值 pyglet.clock.get_sleep_time()

的返回值。 get_sleep_time() 方法是事件循环需要再次迭代之前的秒数(除非有更早的用户输入事件);或 None 循环是否可以无限期地等待输入。

创建自定义事件循环

许多窗口工具包要求应用程序开发人员编写自己的事件循环。这在pyglet中也是可能的,但通常只是与 pyglet.app.run() 。在某些情况下,它可能是必要的,例如在将pyglet与其他工具包组合时,但出于以下原因强烈建议您这样做:

  • 跟踪帧之间的增量时间并保持稳定的帧速率可能是具有挑战性的。很难编写一个不浪费CPU周期并且仍然响应用户输入的手动事件循环。

  • 这个 EventLoop 类为要集成的大多数工具箱提供了大量挂钩,而不需要求助于手动事件循环。

  • 因为 EventLoop 它针对特定的操作系统进行了调整,它对用户事件的响应更快,在调整窗口大小和(在MacOS上)跟踪菜单栏时,它会继续调用时钟函数。

这样,手动事件循环通常具有以下形式:

while True:
    pyglet.clock.tick()
    pyglet.app.platform_event_loop.step(timeout)

    for window in pyglet.app.windows:
        window.switch_to()
        window.dispatch_events()
        window.dispatch_event('on_draw')
        window.flip()

呼唤 pyglet.clock.tick() 是确保调用预定函数所必需的,包括用于播放声音、动画和视频的内部数据泵函数。

这个 dispatch_events() 方法检查窗口的操作系统事件队列中是否有用户输入,并调度找到的任何事件。该方法不等待输入--如果没有挂起的事件,则立即将控制权返回给程序。

这个 dispatch_event('on_draw')() 如果要捕获此窗口事件,则方法是可选的。如果不使用此事件,则绘制将调用 (Batch.draw() )应该放在这里。