努力在Tkinter中为图像设置动画

时间:2017-02-08 22:43:38

标签: python tkinter

我开始编写Connect 4游戏的编码(点击会触发光盘掉落)我想要制作光盘动画。秋季。 所以我首先创建一个新的光盘映像:

discList[y][x] = can.create_image((xCan,yCurrent), image=imgRedDisc, anchor="nw")

光盘在xCan的画布顶部创建; yCurrent。我现在要做的是将光盘放到目的地,即可。我调用我的drop函数,它不断增加光盘的yCurrent,直到它达到yCan的递归和after()方法:

def drop(disc):
    global yCan, yCurrent
    can.move(disc, 0, 1)
    yCurrent += 1
    if yCurrent < yCan:
        can.after(5, drop(disc))

现在我的问题是光盘的中间位置不显示,它只会在几秒后直接显示在底部。 经过一些研究后,我添加了一行来更新画布:

def drop(disc):
    global yCan, yCurrent
    can.move(disc, 0, 1)
    yCurrent += 1
    can.update()
    if yCurrent < yCan:
        can.after(5, drop(disc))

现在我看到我的光盘掉落了,但每次播放后都会变得迟钝;光盘只在我点击后几秒钟开始下降(触发它们摔倒)。另一个问题是,如果我通过非常快速的双击触发两个光盘几乎是相同的,那么第一个光盘会在中途停止下降,然后只是从画布上掉下来。

我的问题是,如何显示光盘的每一步&#39;没有can.update()? 另外我将每个光盘id存储在一个列表(discList)中,是否有更方便的方式来存储动态创建的画布图像?

1 个答案:

答案 0 :(得分:0)

在tkinter中执行动画的正确方法是使用一个执行一帧动画的函数,然后让它自己重复调用直到一些终端条件。

例如:

def move_object(obj_id):
    can.move(obj_id, 0, 1)
    x0,y0,x1,y1 = can.coords(obj_id)
    if y0 < yCan: 
        can.after(5, move_obj, obj_id)

与您所写内容的主要区别在于您错误地使用了after。你是这样做的:

can.after(5, drop(disc))

......这与此完全相同:

result = drop(disc)
can.after(5, drop)

注意区别?与command属性一样,您必须为函数提供引用。然而,您调用函数,然后将结果提供给after

这是一个非常简单的实验示例:

import tkinter as tk

root = tk.Tk()
canvas = tk.Canvas(root, width=200, height=200)
canvas.pack(fill="both", expand=True)

ball = canvas.create_oval(50,0,100,50, fill="red")

def animate(obj_id):
    canvas.move(obj_id, 0, 3)
    x0,y0,x1,y1 = canvas.coords(obj_id)
    if y0 > canvas.winfo_height():
        canvas.coords(obj_id, 50,-50, 100, 0)
    canvas.after(50, animate, obj_id)

animate(ball)
root.mainloop()