Tkinter - 如何以慢动作从 canvas 移动图像
Tkinter - How to move image from canvas in slow motion
伙计们。我正在尝试创建自己的纸牌游戏版本。我在尝试将我的卡片移动到 canvas 单击事件的中心时遇到以下问题。这是我的代码示例
import tkinter as tk
class gui(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.canvas = tk.Canvas(parent, bg="blue", highlightthickness=0)
self.canvas.pack(fill="both", expand=True)
self.img = PhotoImage(file="card.gif")
self.card = self.canvas.create_image(10, 10, image=self.img)
self.canvas.tag_bind(self.card, '<Button-1>', self.onObjectClick1)
def onObjectClick1(self, event):
if self.canvas.find_withtag("current"):
x = 400
y = 400
self.canvas.coords("current", x, y)
self.canvas.tag_raise("current")
if __name__ == "__main__":
root = tk.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))
gui(root)
root.mainloop()
我想要的是移动我的卡片,而不是仅仅从一个坐标移动到另一个坐标,而是给它慢动作效果。
为了 'animate' 你的卡片移动,一个系统会分解要移动的总距离,然后 moving/updating 在一段时间内按较小的距离进行分解。
例如,如果您希望将卡片在 x 和 y 方向移动 400 个单位,则可以使用以下方法:
total_time = 500 #Time in milliseconds
period = 8
dx = 400/period
dy = 400/period
for i in range(period):
self.canvas.move(chosen_card, dx, dy)
root.after(total_time/period) #Pause for time, creating animation effect
root.update() #Update position of card on canvas
这可能是动画的基本前提。当然,您需要编辑我示例中的 total_time
和 period
变量来创建您认为正确的内容。
基本思想是编写一个函数,将对象移动少量,然后安排自身在短暂延迟后再次调用。它会这样做,直到到达目的地。
这是一个非常简单的示例,可以独立移动几个项目。您可以通过更改 speed
参数或更改 delta_x
和 delta_y
的值来调整速度。
这是一个非常简单的算法,只是将 x 和 y 坐标增加一个固定的量。您可以改为计算沿曲线或直线的等距点。无论如何,动画技术保持不变。
import Tkinter as tk
def move_object(canvas, object_id, destination, speed=50):
dest_x, dest_y = destination
coords = canvas.coords(object_id)
current_x = coords[0]
current_y = coords[1]
new_x, new_y = current_x, current_y
delta_x = delta_y = 0
if current_x < dest_x:
delta_x = 1
elif current_x > dest_x:
delta_x = -1
if current_y < dest_y:
delta_y = 1
elif current_y > dest_y:
delta_y = -1
if (delta_x, delta_y) != (0, 0):
canvas.move(object_id, delta_x, delta_y)
if (new_x, new_y) != (dest_x, dest_y):
canvas.after(speed, move_object, canvas, object_id, destination, speed)
root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=400)
canvas.pack()
item1 = canvas.create_rectangle(10, 10, 30, 30, fill="red")
item2 = canvas.create_rectangle(360, 10, 380, 30, fill="green")
move_object(canvas, item1, (200, 180), 25)
move_object(canvas, item2, (200, 220), 50)
root.mainloop()
下面的这段代码(为 copy/paste 和 运行 准备就绪)在我的盒子上提供了一个很好的平滑运动:
import tkinter as tk
import time
class gui(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.canvas = tk.Canvas(parent, bg="blue", highlightthickness=0)
self.canvas.pack(fill="both", expand=True)
self.img = tk.PhotoImage(file="card.gif")
self.card = self.canvas.create_image(10, 10, image=self.img)
self.canvas.tag_bind(self.card, '<Button-1>', self.onObjectClick1)
def onObjectClick1(self, event):
if self.canvas.find_withtag("current"):
x = 400
y = 400
self.canvas.coords("current", x, y)
self.canvas.tag_raise("current")
total_time = 500 #Time in milliseconds
period = 400
dx = 400/period
dy = 400/period
for i in range(period):
self.canvas.move(self.card, dx, dy) # chosen_card
time.sleep(0.01)
# root.after(total_time/period) #Pause for time, creating animation effect
root.update() #Update position of card on canvas
if __name__ == "__main__":
root = tk.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))
gui(root)
root.mainloop()
伙计们。我正在尝试创建自己的纸牌游戏版本。我在尝试将我的卡片移动到 canvas 单击事件的中心时遇到以下问题。这是我的代码示例
import tkinter as tk
class gui(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.canvas = tk.Canvas(parent, bg="blue", highlightthickness=0)
self.canvas.pack(fill="both", expand=True)
self.img = PhotoImage(file="card.gif")
self.card = self.canvas.create_image(10, 10, image=self.img)
self.canvas.tag_bind(self.card, '<Button-1>', self.onObjectClick1)
def onObjectClick1(self, event):
if self.canvas.find_withtag("current"):
x = 400
y = 400
self.canvas.coords("current", x, y)
self.canvas.tag_raise("current")
if __name__ == "__main__":
root = tk.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))
gui(root)
root.mainloop()
我想要的是移动我的卡片,而不是仅仅从一个坐标移动到另一个坐标,而是给它慢动作效果。
为了 'animate' 你的卡片移动,一个系统会分解要移动的总距离,然后 moving/updating 在一段时间内按较小的距离进行分解。
例如,如果您希望将卡片在 x 和 y 方向移动 400 个单位,则可以使用以下方法:
total_time = 500 #Time in milliseconds
period = 8
dx = 400/period
dy = 400/period
for i in range(period):
self.canvas.move(chosen_card, dx, dy)
root.after(total_time/period) #Pause for time, creating animation effect
root.update() #Update position of card on canvas
这可能是动画的基本前提。当然,您需要编辑我示例中的 total_time
和 period
变量来创建您认为正确的内容。
基本思想是编写一个函数,将对象移动少量,然后安排自身在短暂延迟后再次调用。它会这样做,直到到达目的地。
这是一个非常简单的示例,可以独立移动几个项目。您可以通过更改 speed
参数或更改 delta_x
和 delta_y
的值来调整速度。
这是一个非常简单的算法,只是将 x 和 y 坐标增加一个固定的量。您可以改为计算沿曲线或直线的等距点。无论如何,动画技术保持不变。
import Tkinter as tk
def move_object(canvas, object_id, destination, speed=50):
dest_x, dest_y = destination
coords = canvas.coords(object_id)
current_x = coords[0]
current_y = coords[1]
new_x, new_y = current_x, current_y
delta_x = delta_y = 0
if current_x < dest_x:
delta_x = 1
elif current_x > dest_x:
delta_x = -1
if current_y < dest_y:
delta_y = 1
elif current_y > dest_y:
delta_y = -1
if (delta_x, delta_y) != (0, 0):
canvas.move(object_id, delta_x, delta_y)
if (new_x, new_y) != (dest_x, dest_y):
canvas.after(speed, move_object, canvas, object_id, destination, speed)
root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=400)
canvas.pack()
item1 = canvas.create_rectangle(10, 10, 30, 30, fill="red")
item2 = canvas.create_rectangle(360, 10, 380, 30, fill="green")
move_object(canvas, item1, (200, 180), 25)
move_object(canvas, item2, (200, 220), 50)
root.mainloop()
下面的这段代码(为 copy/paste 和 运行 准备就绪)在我的盒子上提供了一个很好的平滑运动:
import tkinter as tk
import time
class gui(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.canvas = tk.Canvas(parent, bg="blue", highlightthickness=0)
self.canvas.pack(fill="both", expand=True)
self.img = tk.PhotoImage(file="card.gif")
self.card = self.canvas.create_image(10, 10, image=self.img)
self.canvas.tag_bind(self.card, '<Button-1>', self.onObjectClick1)
def onObjectClick1(self, event):
if self.canvas.find_withtag("current"):
x = 400
y = 400
self.canvas.coords("current", x, y)
self.canvas.tag_raise("current")
total_time = 500 #Time in milliseconds
period = 400
dx = 400/period
dy = 400/period
for i in range(period):
self.canvas.move(self.card, dx, dy) # chosen_card
time.sleep(0.01)
# root.after(total_time/period) #Pause for time, creating animation effect
root.update() #Update position of card on canvas
if __name__ == "__main__":
root = tk.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))
gui(root)
root.mainloop()