使用 tkinter 的简单动画
Posted
技术标签:
【中文标题】使用 tkinter 的简单动画【英文标题】:simple animation using tkinter 【发布时间】:2012-07-16 10:57:33 【问题描述】:我有一个简单的代码来使用 tkinter 可视化一些数据。单击按钮将绑定到重绘数据的下一个“帧”的函数。但是,我希望可以选择以一定频率自动重绘。在 GUI 编程方面,我非常熟悉(我不需要为这段代码做很多事情),所以我的大部分 tkinter 知识来自于跟随和修改示例。我想我可以使用 root.after 来实现这一点,但我不太确定我是否理解其他代码的方式。我的程序的基本结构如下:
# class for simulation data
# --------------------------------
def Visualisation:
def __init__(self, args):
# sets up the object
def update_canvas(self, Event):
# draws the next frame
canvas.delete(ALL)
# draw some stuff
canvas.create_........
# gui section
# ---------------------------------------
# initialise the visualisation object
vis = Visualisation(s, canvasWidth, canvasHeight)
# Tkinter initialisation
root = Tk()
canvas = Canvas(root, width = canvasWidth, height = canvasHeight)
# set mouse click to advance the simulation
canvas.grid(column=0, row=0, sticky=(N, W, E, S))
canvas.bind('<Button-1>', vis.update_canvas)
# run the main loop
root.mainloop()
很抱歉提出一个问题,我确信这个问题的答案显而易见。非常感谢。
【问题讨论】:
【参考方案1】:使用 Tkinter 执行动画或周期性任务的基本模式是编写一个绘制单个帧或执行单个任务的函数。然后,使用这样的东西定期调用它:
def animate(self):
self.draw_one_frame()
self.after(100, self.animate)
一旦您调用此函数一次,它将继续以每秒 10 帧的速率绘制帧 - 每 100 毫秒一次。如果您希望能够在动画开始后停止动画,则可以修改代码以检查标志。例如:
def animate(self):
if not self.should_stop:
self.draw_one_frame()
self.after(100, self.animate)
然后,您将拥有一个按钮,单击该按钮时会将 self.should_stop
设置为 False
【讨论】:
非常感谢布莱恩;我做过类似的事情,但不知何故我的一个事件绑定把事情搞砸了。现在一切正常。 如果允许无限期运行,第一个版本会导致错误最大递归深度达到 @rahultyagi:不,不可能超过最大递归深度,因为它不是递归函数。至少,不是字面意义上的。该函数不会调用自己,它只是安排自己在未来再次运行。堆栈深度永远不会超过 1。 是的,我刚刚在另一篇文章中读到了这一点,完全被搞糊涂了:) @AlecKeyserWhite: “如果你使用括号调用函数,堆栈深度会增加” - 虽然是这样,但这个答案并不建议使用括号调用函数,所以它不会不断增长的堆栈没有问题。【参考方案2】:我只是想添加 Bryan 的答案。我没有足够的代表发表评论。
另一个想法是使用self.after_cancel()
来停止动画。
所以...
def animate(self):
self.draw_one_frame()
self.stop_id = self.after(100, self.animate)
def cancel(self):
self.after_cancel(self.stop_id)
【讨论】:
以上是关于使用 tkinter 的简单动画的主要内容,如果未能解决你的问题,请参考以下文章
使用带有 pylab/matplotlib 嵌入的 Tkinter 播放、暂停、停止功能的彩色绘图动画:无法更新图形/画布?