【问题标题】:while loop not working in tkinter animationwhile循环在tkinter动画中不起作用
【发布时间】:2016-07-26 20:48:19
【问题描述】:

我正在尝试创建一个转动轮子的动画,并希望在 while 循环中有一个小的延迟,然后每次都更新轮子。我已经尝试过 tkinter 中的“after”函数以及 python 中的“sleep”函数,但它要么崩溃,要么完成计算,并且只在车轮转动时向我显示没有实际动画的最后位置。

我为转轮创建的函数:

def turning():
    #initial wheel position
    global position
    pos(position)

    #infinite loop turning the wheel
    while(1):
        root.after(1000, spin)

def spin():
    global position
    global speed
    delspike() #delete current wheel
    position += speed #calculate next position
    if position > 360:
        position -= 360
    pos(position) #draw new wheel

为什么这不起作用?

【问题讨论】:

  • 在绘制或重绘轮子后尝试调用root.update_idletasks()
  • @Pythonista:不,while True 循环不是解决方案。它会有完全相同的不良行为。

标签: python loops animation tkinter delay


【解决方案1】:

after 用于您尝试放入循环的函数中:

def f():
    ...
    root.after(1000, f)

(1000 表示 1000 毫秒,即 1 秒。这意味着程序将每 1 秒执行一次操作。您可以将其更改为任何您想要的数字。) 另外,请记住,在 Tkinter 中使用无限 while 循环(while Truewhile 1 等)会使窗口不响应。我们在这里讨论了很多。如果你研究过SO,你可以找到这个。

【讨论】:

    【解决方案2】:

    这段代码:

    while (1):
        root.after(1000, spin)
    

    .. 将安排 spin 函数在 1 秒内运行。它会在眨眼之间完成数千次。即使您要求spin 在一秒钟内运行,while 循环本身也会尽可能快地运行并且永远不会停止。它将在第一次旋转之前安排数十万次旋转,然后它们将一个接一个地运行,因为它们都将尝试在一秒钟内运行。

    做动画的正确方法是让函数在一秒钟内再次调度自己:

    def spin():
        ...
        root.after(1000, spin)
    

    然后,您在程序开始时只调用一次spin,它会无限期地运行。

    【讨论】:

      【解决方案3】:

      我注意到许多“不知道更好”的初学者尝试使用 while 循环为 tkinter 设置动画。事实证明,这不是一个愚蠢的想法。我最近想出了如何使用 asyncio 和 3.5 中的新 async-await 语法来完成这项工作。我还为一个简单的应用程序制定了一个通用模板。我碰巧喜欢这种风格而不是使用后循环。如果您安装了 3.5.2 或 3.6.0a3(或安装其中任何一个),您可以运行此代码并将我的 rotator 替换为您的。

      import asyncio
      import tkinter as tk
      
      
      class App(tk.Tk):
      
          def __init__(self, loop, interval=1/120):
              super().__init__()
              self.loop = loop
              self.protocol("WM_DELETE_WINDOW", self.close)
              self.tasks = []
              self.tasks.append(loop.create_task(
                      self.rotator(1/60, 1)))
              self.updater(interval)
      
          async def rotator(self, interval, d_per_int):
              canvas = tk.Canvas(self, height=600, width=600)
              canvas.pack()
              deg = 0
              arc = canvas.create_arc(100, 100, 500, 500,
                                      start=0, extent=deg, fill='blue')
              while True:
                  await asyncio.sleep(interval)
                  deg = (deg + d_per_int) % 360
                  canvas.itemconfigure(arc, extent=deg)
      
          def updater(self, interval):
              self.update()
              self.loop.call_later(interval, self.updater, interval)
      
          def close(self):
              for task in self.tasks:
                  task.cancel()
              self.loop.stop()
              self.destroy()
      
      
      loop = asyncio.get_event_loop()
      app = App(loop)
      loop.run_forever()
      loop.close()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-19
        • 1970-01-01
        • 2015-08-02
        • 2017-11-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多