今天开始玩python的tkinter并遇到了一些问题.我创建了一个动画,以给定的速度在屏幕上移动球.(当它击中屏幕时,它会返回)
为什么我的球看起来很糟糕?它的形状不均匀?(它像眨眼一样)
有没有更好的方法呢?
代码:
from tkinter import *
import time
WIDTH = 800
HEIGHT = 500
SIZE = 100
tk = Tk()
canvas = Canvas(tk, width=WIDTH, height=HEIGHT, bg="grey")
canvas.pack()
color = 'black'
class Ball:
def __init__(self):
self.shape = canvas.create_oval(0, 0, SIZE, SIZE, fill=color)
self.speedx = 3
self.speedy = 3
def update(self):
canvas.move(self.shape, self.speedx, self.speedy)
pos = canvas.coords(self.shape)
if pos[2] >= WIDTH or pos[0] <= 0:
self.speedx *= -1
if pos[3] >= HEIGHT or pos[1] <= 0:
self.speedy *= -1
ball = Ball()
while True:
ball.update()
tk.update()
time.sleep(0.01)
Run Code Online (Sandbox Code Playgroud)
终止程序后的错误:
Traceback (most recent call last):
File "C:/..py", line 29, in <module>
ball.update()
File "C:/Users/talsh/...py", line 20, in update
canvas.move(self.shape, self.speedx, self.speedy)
File "C:\Users\...\tkinter\__init__.py", line 2585, in move
self.tk.call((self._w, 'move') + args)
_tkinter.TclError: invalid command name ".!canvas"
Run Code Online (Sandbox Code Playgroud)
这是正常的吗?我做错了吗?
我想成像的问题来自于sleep()
.这些方法sleep()
和wait()
不应该在Tkinter的使用,因为它们会暂停整个应用程序,而不是仅仅提供一个计时器.
更新:命名一个与内置方法同名的方法也不是一个好主意.
你已经self.update()
并且update()
已经在画布的名称空间中了.换成self.update()
其他类似的东西:self.ball_update()
更新:看起来tikinter以15毫秒的速度刷新并试图以比这更快的速度发射可能导致问题.最接近我能够阻止圆圈扭曲,同时以与原始代码相同的速率移动,将计时器更改为30毫秒,并将速度变量从3更改为9.
始终确保你有mainloop()
tkinter应用程序的结尾.mainloop()
需要确保tkinter正常运行,没有可能因为它丢失而导致的错误,所以最后添加tk.mainloop()
你应该使用after()
.这可能应该使用函数/方法作为您的定时循环.像这样的东西:
def move_active(self):
if self.active == True:
self.ball_update()
tk.after(30, self.move_active)
tk.update()
Run Code Online (Sandbox Code Playgroud)
用上面的方法替换while循环,并将class属性添加self.active = True
到您的__init__
部分.如果这清除了你的口吃,请告诉我:
from tkinter import *
import time
WIDTH = 800
HEIGHT = 500
SIZE = 100
tk = Tk()
canvas = Canvas(tk, width=WIDTH, height=HEIGHT, bg="grey")
canvas.pack()
color = 'black'
class Ball:
def __init__(self):
self.shape = canvas.create_oval(0, 0, SIZE, SIZE, fill=color)
self.speedx = 9 # changed from 3 to 9
self.speedy = 9 # changed from 3 to 9
self.active = True
self.move_active()
def ball_update(self):
canvas.move(self.shape, self.speedx, self.speedy)
pos = canvas.coords(self.shape)
if pos[2] >= WIDTH or pos[0] <= 0:
self.speedx *= -1
if pos[3] >= HEIGHT or pos[1] <= 0:
self.speedy *= -1
def move_active(self):
if self.active == True:
self.ball_update()
tk.after(30, self.move_active) # changed from 10ms to 30ms
ball = Ball()
tk.mainloop() # there should always be a mainloop statement in tkinter apps.
Run Code Online (Sandbox Code Playgroud)
以下是与刷新计时器相关的Q/A的一些链接.
所有这一切,你可能想要使用一个可能能够以更快的重新刷新率运行的替代品,如Pygame
更新:
这是一个圆圈在画布中移动时发生的事情的图像.正如你所看到的那样,圆圈的药水明显被切断了.这似乎发生更新设置得越快.更新速度越慢(大多数超过15毫秒)以减少此问题: