Вы не должны использовать while
или sleep
в том же потоке, в котором запущен tkinter.
В этом случае при использовании after()
он работает точно так же, как sleep
.
Поскольку tkinter является однопоточным, эти методы блокируют основной цикл, и больше ничего не может произойти, пока цикл не закончится или не закончится спящий режим. Причина, по которой ваш холст обновляется, заключается в том, что вы вызываете update в цикле while, но ваши события по-прежнему блокируются.
Чтобы исправить это, используйте after()
, как это предусмотрено для этого вида цикла в tkinter.
Я обновил ваш код для использования after()
и немного его очистил, чтобы более точно следовать руководству по стилю PEP8. дайте мне знать, если у вас есть какие-либо вопросы.
import tkinter as tk
class RacingCar(tk.Tk):
def __init__(self):
super().__init__()
self.title("Racing Car")
self.c_width = 500
self.c_height = 200
self.canvas = tk.Canvas(self, width=self.c_width, height=self.c_height, bg="white")
self.canvas.pack()
self.x = 0
self.y = self.c_height
self.draw_car(self.x, self.y)
self.dx = 5
self.after_time = 50
self.animate()
self.bind("<Up>", self.increase_speed)
self.bind("<Down>", self.decrease_speed)
def draw_car(self, x, y):
self.canvas.create_rectangle(x, y - 20, x + 50, y - 10, fill="yellow", tags="car")
self.canvas.create_oval(x + 10, y - 10, x + 20, y, fill="black", tags="car")
self.canvas.create_oval(x + 30, y - 10, x + 40, y, fill="black", tags="car")
self.canvas.create_polygon([x + 10, y - 20, x + 20, y - 30, x + 30, y - 30, x + 40, y - 20],
fill="blue", tags="car")
def increase_speed(self, _):
print("pressed up")
self.dx += 2.5
def decrease_speed(self, _):
print("pressed down")
if self.dx > 0:
self.dx -= 2.5
def animate(self):
if self.dx != 0:
self.canvas.move("car", self.dx, 0)
if self.x < self.c_width + 10:
self.x += self.dx
else:
self.x = -60
self.canvas.delete("car")
self.draw_car(self.x, self.y)
self.after(self.after_time, self.animate)
RacingCar().mainloop()