正如所建议的那样,我开始使用.after方法来创建弹跳球GUI,并再次成为一个问题。
from tkinter import*
from tkinter import ttk
import random
class Widg:
def __init__(self, master):
master.geometry('600x500+200+150')
canvas = Canvas(master)
canvas.pack(fill=BOTH, expand=True)
oval = canvas.create_oval(1, 1, 11, 11, fill='green')
def call_func(self):
for i in range(3):
rand_x = random.randint(1, 50)
rand_y = random.randint(1, 50)
canvas.move(oval, rand_x, rand_y)
canvas.after(500)
print('x= ', rand_x)
print('y= ', rand_y)
canvas.bind('<ButtonPress-1>', call_func)
def main():
root = Tk()
a = Widg(root)
root.mainloop()
if __name__ == '__main__':
main()
而且,当我启动它时,它会在小部件后面运行,只显示最终结果。 (没有动画)
UPD .: upd2。:@ tobias_k正式注意到!不会再发生了!谢谢你的回答!
答案 0 :(得分:2)
您必须在after
中指定要调用的函数 - 在您的情况下,调用它的函数相同。如上所述in comments,没有回调函数,after
行为就像sleep
一样(除了参数是以毫秒而不是秒为单位),即它将等待给定的时间,但这样做会阻止UI,这样就不会注册任何输入,特别是球不是重新绘制直到循环之后。通过回调调用after
,每次重新定位和重绘球时,无限期地再次调用该函数。
另请注意,call_func
的参数不是 self
(与原始代码中一样) - 它不是该类的方法,但是嵌套函数 - 但鼠标单击发出event
。您应该将此设置为default-parameter,因为使用after
时不会发生任何事件(并且您也不需要它)。此外,似乎没有必要循环;如果您希望球移动得更快,请缩短after
的时间,并且self
变量使用rand_x/y
毫无意义。
def call_func(event=None):
rand_x = random.randint(-50, 50)
rand_y = random.randint(-50, 50)
self.canvas.move(self.oval, rand_x, rand_y)
self.canvas.after(150, call_func)
如果您希望仅在有限次数内回调函数,则可以添加另一个参数,跟踪重复次数:
def call_func(event=None, repeat=10):
rand_x = random.randint(-50, 50)
rand_y = random.randint(-50, 50)
self.canvas.move(self.oval, rand_x, rand_y)
if repeat:
self.canvas.after(150, lambda: call_func(repeat=repeat-1))