【问题标题】:using after method with tkinter在 tkinter 中使用 after 方法
【发布时间】:2018-02-19 09:41:25
【问题描述】:

按照建议,我开始使用 .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()

同样,当我启动它时,它会在小部件后面运行并简单地显示最终结果。 (无动画)

更新: upd2.:@tobias_k 已正式注明!不会再发生了!感谢您的回答!

【问题讨论】:

  • 您对after 的调用似乎缺少一些参数。也许它在错误的时间被调用。
  • 书上说:也可以省略回调。如果这样做,此方法只是等待给定的毫秒数,而不提供任何事件(与 time.sleep(delay_ms*0.001) 相同)。所以基本上, w.after(500) 应该可以工作,不是吗?
  • @DEN_VER (1) 请不要只修改您的代码,而是在原始代码下方发布更新版本,以免现有答案无效; (2)请求回答者的反馈,在他们的答案下方评论,而不是在问题下方,以便他们得到通知(我只是偶然回来); (3) 你仍然没有修复对after的调用。
  • @tobias_k 谢谢,我退回了。你是对的,现在它可以工作了。
  • @tobias_k: after(500) 与调用睡眠相同,并且正如名称“睡眠”所暗示的那样:它使整个 GUI 进入睡眠状态。您永远不应该这样做,因为 GUI 无法处理 任何 事件,包括刷新显示的请求。

标签: python tkinter tkinter-canvas


【解决方案1】:

您必须指定要在after 中调用的函数——在您的情况下,调用它的函数相同。如in comments 所述,没有回调函数,after 的行为就像sleep (除了参数是毫秒而不是秒),即它将等待给定的时间,但这样做会阻塞 UI,这样就不会注册任何输入,特别是直到循环之后才会重绘球。通过使用回调调用after,您可以无限期地再次调用该函数,每次都重新定位和重新绘制球。

另外,请注意call_func 的参数不是 self(就像在原始代码中一样)——它不是类的方法,而是嵌套函数—— ——但是event是鼠标点击发出的。您应该将此设置为默认参数,因为在使用 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))

【讨论】:

    猜你喜欢
    • 2014-11-03
    • 1970-01-01
    • 2014-02-01
    • 2021-02-16
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    • 2021-09-24
    相关资源
    最近更新 更多