在Tkin中使物体以圆形路径移动

2024-04-18 22:34:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我在尝试用圆圈在画布上移动来模拟一个简单的太阳系。然而,我一直在试图找到一种方法来为它们设置动画。我环顾四周,发现move函数与after相结合,可以创建一个动画循环。我试图通过改变参数来改变y偏移并在弯曲路径中创建移动,但是当我尝试递归地或者使用while循环来实现这一点时,我失败了。以下是我目前掌握的代码:

import tkinter

class celestial:
    def __init__(self, x0, y0, x1, y1):
        self.x0 = x0
        self.y0 = y0
        self.x1 = x1
        self.y1 = y1

sol_obj = celestial(200, 250, 250, 200)
sx0 = getattr(sol_obj, 'x0')
sy0 = getattr(sol_obj, 'y0')
sx1 = getattr(sol_obj, 'x1')
sy1 = getattr(sol_obj, 'y1')
coord_sol = sx0, sy0, sx1, sy1

top = tkinter.Tk()

c = tkinter.Canvas(top, bg='black', height=500, width=500)
c.pack()

sol = c.create_oval(coord_sol, fill='black', outline='white')

top.mainloop()

Tags: selfobjtkintertop动画x1y1getattr
1条回答
网友
1楼 · 发布于 2024-04-18 22:34:46

下面是一个使用tkinterafter方法更新对象和关联的canvasoval对象位置的方法。它使用一个生成器函数来计算圆形路径上的坐标,该路径表示Celestial实例(名为planet_obj1)之一的轨道。在

import math
try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk  # Python 2

DELAY = 100
CIRCULAR_PATH_INCR = 10

sin = lambda degs: math.sin(math.radians(degs))
cos = lambda degs: math.cos(math.radians(degs))

class Celestial(object):
    # Constants
    COS_0, COS_180 = cos(0), cos(180)
    SIN_90, SIN_270 = sin(90), sin(270)

    def __init__(self, x, y, radius):
        self.x, self.y = x, y
        self.radius = radius

    def bounds(self):
        """ Return coords of rectangle surrounding circlular object. """
        return (self.x + self.radius*self.COS_0,   self.y + self.radius*self.SIN_270,
                self.x + self.radius*self.COS_180, self.y + self.radius*self.SIN_90)

def circular_path(x, y, radius, delta_ang, start_ang=0):
    """ Endlessly generate coords of a circular path every delta angle degrees. """
    ang = start_ang % 360
    while True:
        yield x + radius*cos(ang), y + radius*sin(ang)
        ang = (ang+delta_ang) % 360

def update_position(canvas, id, celestial_obj, path_iter):
    celestial_obj.x, celestial_obj.y = next(path_iter)  # iterate path and set new position
    # update the position of the corresponding canvas obj
    x0, y0, x1, y1 = canvas.coords(id)  # coordinates of canvas oval object
    oldx, oldy = (x0+x1) // 2, (y0+y1) // 2  # current center point
    dx, dy = celestial_obj.x - oldx, celestial_obj.y - oldy  # amount of movement
    canvas.move(id, dx, dy)  # move canvas oval object that much
    # repeat after delay
    canvas.after(DELAY, update_position, canvas, id, celestial_obj, path_iter)

top = tk.Tk()
top.title('Circular Path')

canvas = tk.Canvas(top, bg='black', height=500, width=500)
canvas.pack()

sol_obj = Celestial(250, 250, 25)
planet_obj1 = Celestial(250+100, 250, 15)
sol = canvas.create_oval(sol_obj.bounds(), fill='yellow', width=0)
planet1 = canvas.create_oval(planet_obj1.bounds(), fill='blue', width=0)

orbital_radius = math.hypot(sol_obj.x - planet_obj1.x, sol_obj.y - planet_obj1.y)
path_iter = circular_path(sol_obj.x, sol_obj.y, orbital_radius, CIRCULAR_PATH_INCR)
next(path_iter)  # prime generator

top.after(DELAY, update_position, canvas, planet1, planet_obj1, path_iter)
top.mainloop()

下面是跑步的样子:

{a1}

相关问题 更多 >