使用Tkinter实现弹跳球:类封装后小球无法移动问题求助
问题分析与解决方案
嘿,这个问题我刚学Tkinter的时候也踩过!核心原因很简单:你没有保存Canvas创建椭圆后返回的图形ID,反而把自定义的Ball实例传给了canvas.move()。
为什么直接创建能运行?
你直接写ball1 = canvas.create_oval(...)时,ball1存储的是Canvas返回的整数ID——这是Canvas用来识别自己创建的图形对象的唯一标识,canvas.move()就是靠这个ID找到要移动的图形的。
类封装哪里错了?
在你的Ball类里:
__init__里创建了椭圆,但没有把返回的ID存在实例里,相当于创建完就丢了这个关键标识;move方法里调用canvas.move(self, dx, dy),这里的self是Ball类的实例对象,不是Canvas的图形ID,Canvas根本不知道你要移动哪个图形,自然不会有任何反应(也不会报错,因为Canvas接收无效ID时会静默忽略)。
修改后的代码
只需要给Ball类加一个实例属性存储图形ID,再在move方法里用这个ID就行:
""" 修改后的Ball类 """ class Ball: def __init__(self, posx, posy, r): # 把Canvas返回的图形ID存为实例属性 self.id = canvas.create_oval(posx-r, posy-r, posx+r, posy+r, fill ="red") def move(self, dx, dy): # 用self.id代替self传给canvas.move canvas.move(self.id, dx, dy) ball1 = Ball(50,50,10) while True: ball1.move(xspeed, yspeed) window.update() time.sleep(0.05)
额外小建议
另外,Tkinter本身有自己的事件循环(window.mainloop()),用while True加time.sleep的方式其实不太规范,容易导致界面卡顿。如果想让动画更流畅,可以用window.after()来实现定时触发移动,比如:
def animate(): ball1.move(xspeed, yspeed) # 每隔50毫秒调用一次animate,形成循环 window.after(50, animate) # 启动动画 animate() window.mainloop()
这样就不用自己写死循环啦,Tkinter会帮你管理事件~
内容的提问来源于stack exchange,提问作者Nannith
相关产品推荐
相关产品推荐

