使用Tkinter Python创建简单动画

3

我在寻找一个使用Tkinter的简单动画代码,但我找到了很多不同的例子,无法理解正确的编写动画的方式。这是我的工作代码,用于显示一个简单的移动圆:

import tkinter as tk
import time

root=tk.Tk()
canvas=tk.Canvas(root,width=400,height=400)
canvas.pack()
circle=canvas.create_oval(50,50,80,80,outline="white",fill="blue")

def redraw():
   canvas.after(100,redraw)
   canvas.move(circle,5,5)
   canvas.update()
canvas.after(100,redraw)
root.mainloop()

在这段代码中,我无法正确理解:after方法是如何工作的,在哪里正确放置update和move方法(在after方法之前吗?),是否有其他编写动画代码的方法?您可以向我发布另一个示例并评论代码吗? 谢谢 :)

更新没有任何作用,你想要发生什么? - Padraic Cunningham
我需要一个简单的动画,在我的应用程序中创建一个多边形并移动它。 - Cassandra
@PadraicCunningham:它不是什么都不做——它实际上会执行某些操作。它会处理所有待处理事件。 - Bryan Oakley
@BryanOakley,这对OP的代码有什么影响? - Padraic Cunningham
@PadraicCunningham:就像我说的,它会处理所有待处理事件。在这种特定情况下,由于没有事件绑定,所以是无害的,但“无害”并不等同于“什么也没有”,因为它实际上确实会处理任何待处理事件。它执行的工作与mainloop相同,但只执行一次,而不是持续执行。 - Bryan Oakley
2个回答

1

调用update

您不应该调用canvas.update()。一般来说,您永远不应该调用update。关于为什么,请参见this essay,这篇文章是底层tcl解释器的原始开发人员之一撰写的。

如果您删除对canvas.update()的调用,则可以正确地在tkinter程序中执行动画。

使用after启动动画

您不需要在调用root.mainloop()之前立即调用after。这样做同样有效:

...
redraw()
root.mainloop()

在这种特定情况下,使用或不使用after取决于您是否希望动画立即开始(甚至可能在小部件可见之前)或者您希望它在短暂延迟后发生(可能在小部件可见之后)。 after的工作原理如下: mainloop只是一个无限循环,检查事件队列中的事件。当它找到一个事件时,它会将其从列表中弹出并处理它。 after只是发出一个请求,请求说“在100毫秒内,请向队列添加一个新事件”。当时间限制到期时,将向队列添加一个事件,该事件实际上是“运行此命令”。下次循环检查事件时,它会看到此事件,将其从队列中取出并运行命令。
当你在一个被after调用的方法中再次调用after时,实际上是在创建一个无限循环,意思是“等待100ms并再次执行”。如果你在移动对象之前调用after,就是在说“每100ms运行一次这个函数”。如果你在移动对象之后调用它,就是在说“在上一次运行后100ms再次运行此函数”。这个差别非常微妙,通常不会察觉到,除非你的函数需要很长时间才能运行完。

你是否有不调用.update的理由?如果你在循环中改变了某些东西,例如制作加载屏幕,那么使用它可以强制显示动画在屏幕上,似乎是一个非常有用的功能。 - ChronoVortex
@RedstoneReforged:这篇文章是由一位编写了底层tcl解释器的内部代码的人撰写的,可能是目前最好的解释。 - Bryan Oakley

0

我的代码是:

from tkinter import *
import time
tk = Tk()
płótno = Canvas(tk, width=500, height=500)
płótno.pack()
płótno.create_polygon(10,10,10,70,70,10,fill="blue",outline="black")
for x in range(0,51):
   płótno.move(1,5,0)
   płótno.update()
   rest(0.05)

płótno 意味着画布


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接