动画化对象以在Tkinter中的圆形路径中移动

发布于 2021-01-29 15:03:50

我正在尝试使用圆在Tkinter中为一个简单的太阳系建模,并在画布中四处移动。但是,我一直在努力寻找一种使它们动起来的方法。我环顾四周,发现该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()
关注者
0
被浏览
77
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    这里显示了一种使用tkinterafter方法更新对象和关联的画布oval对象的位置的方法。它使用生成器函数沿圆形路径计算坐标,该圆形路径表示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()
    

    这是运行的样子:

    动画图像显示它正在运行



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看