如何在不等待循环结束的情况下并发运行同一方法?

时间:2018-09-22 13:11:31

标签: python function loops methods concurrency

从下面的代码中可以看到,我有一个函数,当用户单击窗口时,该函数会产生一个圆的动画。我的问题是,对于已经生成的另一个圆,我要使其出现并移动,我必须等待上一个圆完成其移动循环。在降雪功能结束时,一个圆圈完成其“ i in range”循环后,我可以单击以产生另一个圆圈。我希望能够随时单击,并且可以使任意多个圆圈同时移动(我知道我已将该函数下的代码限制为10次)。看来我需要同时执行多次相同的方法。

from graphics import*
from random import*


win = GraphWin("Graphics Practice", 500, 500)

colours = ["blue", "red", "orange", "purple", "green", "black", "brown", "yellow", "pink"]

def snowfall(randColour):
    point = win.getMouse()
    circle = Circle(point, 40)
    circle.draw(win)
    circle.setFill(colours[randColour])
    for i in range(1000):
        circle.move(0, 1)
        time.sleep(0.002)

randColour = randint(0, 8)
for i in range (10):
    repeatColour = randColour
    snowfall(randColour)
    randColour = randint(0, 8)
    while randColour == repeatColour:
        randColour = randint(0, 8)

win.getMouse()
win.close()

我的多线程尝试失败之一:

from graphics import*
from random import*


win = GraphWin("Graphics Practice", 500, 500)

colours = ["blue", "red", "orange", "purple", "green", "black", "brown", "yellow", "pink"]

def snowfall(randColour):
    point = win.getMouse()
    circle = Circle(point, 40)
    circle.draw(win)
    circle.setFill(colours[randColour])
    for i in range(1000):
        circle.move(0, 1)
        time.sleep(0.002)

randColour = randint(0, 8)
t1 = threading.Thread(target = snowfall, args = randColour)
for i in range (10):
    repeatColour = randColour
    t1.start()
    t1.join()
    randColour = randint(0, 8)
    while randColour == repeatColour:
        randColour = randint(0, 8)

win.getMouse()
win.close()

最新代码:

from graphics import*
from random import*


win = GraphWin("Graphics Practice", 500, 500)

colours = ["blue", "red", "orange", "purple", "green", "black", "brown", "yellow", "pink"]

class Snowflake(object):
    def __init__(self, randColour):
        self.circle = Circle(point, 40)
        self.circle.draw(win)
        self.circle.setFill(colours[randColour])

    def next_frame(self):
        self.circle.move(0, 1)

randColour = randint(0, 8)
sprites = []    
for i in range (100):
    repeatColour = randColour
    point = win.getMouse()
    sprites.append(Snowflake(randColour))
    randColour = randint(0, 8)
    while randColour == repeatColour:
        randColour = randint(0, 8)
    for s in sprites:
        while True:
            s.next_frame()
            time.sleep(0.02)
    win.getMouse()
    randColour = randint(0, 8)
    sprites.append(Snowflake(randColour, point))

win.getMouse()
win.close()

1 个答案:

答案 0 :(得分:2)

一个问题是您尝试在启动join线程t1之后立即使用它。要join,一个线程要等待它完成,所以您要先启动然后再等待一个线程十次,而不是启动十个线程。

但是,此处的线程处理方法是错误的。出于良好的性能和流畅性,大多数图形包都不允许多个线程绘制到相同的图形上下文。这意味着您需要将绘图线程“由内而外”旋转,将每个动画对象的状态放在“精灵”中,以便每个动画对象的状态都在其自己的实例中。然后,您不必遍历所有精灵,而是遍历所有精灵并在一个循环中对其进行更新,如下所示。

(请注意,我引入了win.checkMouse(),它对鼠标事件进行了非阻塞检查,因此允许您为每次单击添加一个精灵,这正是我所希望的。)

from graphics import *
from random import *

win = GraphWin("Graphics Practice", 500, 500)

colours = ["blue", "red", "orange", "purple", "green", "black", "brown", "yellow", "pink"]

class Snowflake(object):
    def __init__(self, randColour, point):
        self.circle = Circle(point, 40)
        self.circle.draw(win)
        self.circle.setFill(colours[randColour])

    def next_frame(self):
        self.circle.move(0, 1)

randColour = randint(0, 8)
sprites = []
for i in range(100):
    point = win.checkMouse()
    if point:
        randColour = randint(0, 8)
        sprites.append(Snowflake(randColour, point))
    for s in sprites:
        s.next_frame()
    time.sleep(0.1)
win.close()