2017-02-08 117 views
1

我已經開始編寫連接4遊戲(點擊觸發光盤下落),並且我想要爲光盤的下落製作動畫。 於是我開始通過創建一個新的光盤映像:努力在Tkinter中創建動畫

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

盤以在xCan畫布上創建的; yCurrent。我現在想要做的就是讓光盤落到目的地,yCan。我把它不斷遞增光盤的yCurrent我滴功能,直到它到達yCan與遞歸性和後()方法:

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)) 

現在我能看到我的盤落,但它得到各自發揮後laggy;光盤只在點擊後幾秒鐘後開始下降(這會觸發它們的下落)。另一個問題是,如果我通過雙擊非常迅速地觸發兩個光盤幾乎完全一致地倒下,第一個光盤中途停止下落,然後簡單地從畫布上掉下來。

我的問題是,我如何顯示我的光盤的每一個步驟沒有can.update()? 另外我將每個光盤ID存儲在列表(discList)中,是否有更方便的方式來存儲動態創建的畫布圖像?

回答

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()