Tkinter 无法识别按键
Tkinter won't recognize key presses
我正在尝试编写一个程序,以便绘制一辆沿着屏幕移动的汽车,上下箭头键可以改变汽车的速度。但是,当我按下任一键时,都不会调用任何命令。我试过将 bind_all 和焦点线更改为 self.canvas 但这也没有用。我该如何解决这个问题?
class racingCar:
def __init__(self):
window = Tk()
window.title("Racing Car")
self.cWidth = 500
self.cHeight = 200
self.canvas = Canvas(window, width = self.cWidth, height = self.cHeight, bg = "white")
self.canvas.pack()
self.x = 0
self.y = self.cHeight
self.drawCar(self.x, self.y)
self.dx = 5
self.sleepTime = 50
self.animate()
window.bind_all("<Up>", self.increaseSpeed)
window.bind_all("<Down>", self.decreaseSpeed)
window.focus()
window.mainloop()
def drawCar(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 increaseSpeed(self, event):
print("pressed up")
self.dx += 2.5
def decreaseSpeed(self, event):
print("pressed down")
if self.dx > 0:
self.dx -= 2.5
def animate(self):
while not self.dx == 0:
self.canvas.move("car", self.dx, 0)
self.canvas.after(self.sleepTime)
self.canvas.update()
if self.x < self.cWidth + 10:
self.x += self.dx
else:
self.x = -60
self.canvas.delete("car")
self.drawCar(self.x, self.y)
racingCar()
你不应该在同一个线程中使用 while
或 sleep
tkinter 是 运行 in.
在这种情况下,您使用 after()
的方式与 sleep
完全一样。
因为 tkinter 是单线程的,所以这些方法将阻塞主循环,并且在循环结束或睡眠结束之前不会发生任何其他事情。您的 canvas 被更新的原因是因为您在 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()
我正在尝试编写一个程序,以便绘制一辆沿着屏幕移动的汽车,上下箭头键可以改变汽车的速度。但是,当我按下任一键时,都不会调用任何命令。我试过将 bind_all 和焦点线更改为 self.canvas 但这也没有用。我该如何解决这个问题?
class racingCar:
def __init__(self):
window = Tk()
window.title("Racing Car")
self.cWidth = 500
self.cHeight = 200
self.canvas = Canvas(window, width = self.cWidth, height = self.cHeight, bg = "white")
self.canvas.pack()
self.x = 0
self.y = self.cHeight
self.drawCar(self.x, self.y)
self.dx = 5
self.sleepTime = 50
self.animate()
window.bind_all("<Up>", self.increaseSpeed)
window.bind_all("<Down>", self.decreaseSpeed)
window.focus()
window.mainloop()
def drawCar(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 increaseSpeed(self, event):
print("pressed up")
self.dx += 2.5
def decreaseSpeed(self, event):
print("pressed down")
if self.dx > 0:
self.dx -= 2.5
def animate(self):
while not self.dx == 0:
self.canvas.move("car", self.dx, 0)
self.canvas.after(self.sleepTime)
self.canvas.update()
if self.x < self.cWidth + 10:
self.x += self.dx
else:
self.x = -60
self.canvas.delete("car")
self.drawCar(self.x, self.y)
racingCar()
你不应该在同一个线程中使用 while
或 sleep
tkinter 是 运行 in.
在这种情况下,您使用 after()
的方式与 sleep
完全一样。
因为 tkinter 是单线程的,所以这些方法将阻塞主循环,并且在循环结束或睡眠结束之前不会发生任何其他事情。您的 canvas 被更新的原因是因为您在 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()