将Asyncio任务与实时Pyglet(绘图)更新同步

发布时间:2020-07-07 09:54

在asyncio计划​​任务时如何运行pyglet循环?
在下面的示例中,pyglet窗口的图形缺少(与偶尔的控制台输出相比)。

异步任务(用于演示)是:
(1)将三个选项之一随机添加到列表中
(2)随机选择发作时间和持续时间(该选项在列表中保留的时间)
(3)在保留选项的情况下将控制权返回给循环

import asyncio
import random
import pyglet
from pyglet import shapes

# global variables
selection = [] # gets filled
options = list(range(3))

# pyglet functions
class pyglet_window(pyglet.window.Window):
    def __init__(self, w, h, name=""):
        super().__init__(w, h, name, resizable=True)
        self.width  = w
        self.height = h
        self.alive = True
    def on_draw(self):
        self.clear()
        for s in selection:
            self.draw_option(s)
    def draw_option(self, ind):
        x = (ind+0.5)*(self.width)/3
        y = self.height/2
        circle = shapes.Circle(x, y, self.height/2)
        circle.draw()
    def on_close(self):
        self.alive = False

# manual pyglet update loop to gain control over when to call it
async def manual_pyglet_update(win):
    #pyglet.clock.tick()
    win.dispatch_events()
    win.dispatch_event('on_draw')
    win.flip()

def realtime_output():
    output = "|"
    for i in range(len(options)):
        output += "X|" if i in selection else " |"
    print(output) # realtime user feedback

#create task to run concurrently
async def select(option, delay):
    if option not in selection:
        selection.append(option)
        realtime_output()
        await asyncio.sleep(delay) # should give control back to loop
        if option in selection:
            selection.remove(option)
            realtime_output()

#start the asynchronous loop
w = pyglet_window(3*50, 50)
while w.alive:
    await manual_pyglet_update(w)
    start_delay = random.uniform(0.1, 2)
    await asyncio.sleep(start_delay) # i.e. functions not called right away
    keep_delay = random.uniform(0.1, 2)
    option = options[random.randint(0, len(options)-1)]
    task = asyncio.create_task(select(option, keep_delay))
回答1
thread-synchronization 相关推荐