Python tkinter can'中的画布;不能通过按键功能进行更改
我正在学习python tkinter。 我想写一个这样的特写,当我按下“a”键时,球就会停下来为什么我按下键盘,该功能可以运行,但不会改变画布Python tkinter can'中的画布;不能通过按键功能进行更改,python,python-3.x,tkinter,Python,Python 3.x,Tkinter,我正在学习python tkinter。 我想写一个这样的特写,当我按下“a”键时,球就会停下来为什么我按下键盘,该功能可以运行,但不会改变画布 tk = tkinter.Tk() canvas = tkinter.Canvas(tk,width=500, height=400, bd=0, highlightthickness=0) canvas.pack() circle=canvas.create_oval(50,50,80,80, fill="yellow") d
tk = tkinter.Tk()
canvas = tkinter.Canvas(tk,width=500, height=400, bd=0, highlightthickness=0)
canvas.pack()
circle=canvas.create_oval(50,50,80,80, fill="yellow")
dir = True
def stop(event):
dir = False
def move_func():
canvas.move(circle, 0, 1)
def key_stop():
tk.bind_all("a",stop)
while dir:
move_func()
key_stop()
canvas.update_idletasks()
canvas.update()
tk.mainloop()
我试着用停止功能打印一些东西,效果很好。但如果我想在画布上添加一个椭圆形或改变一些东西,它就不起作用了。谢谢。这是因为
stop()
中的dir
是一个局部变量,而不是全局变量。您需要在stop()中添加global dir
:
def stop():
全局目录
dir=False
但是,不建议在tkinter应用程序中使用while循环。改用after()
:
导入tkinter
tk=tkinter.tk()
canvas=tkinter.canvas(tk,宽度=500,高度=400,bd=0,highlightthickness=0)
canvas.pack()
圆圈=画布。创建椭圆(50,50,80,80,fill=“黄色”)
dir=True
def停止(事件):
全局目录
dir=False
def move_func():
如果目录:
画布移动(圆圈,0,1)
tk.在(5,move_func)之后
全部绑定(“a”,停止)
move_func()#开始移动圆
tk.mainloop()
您可以使用创建的变量来管理状态,而不是使用任意变量来管理状态,这些变量比您的任意变量更有意义。让我们考虑一下。现在你的代码是非常小的,但它会保持这种状态吗?在1000行中,dir
对您意味着什么。。。5000行?这是一个方向吗?哪个方向?它是目录吗?哪个目录?如果您需要在按下“a”时将代码移动到绝对停止,而不是执行最后一个延迟过程,该怎么办?您的dir
var无法管理这一点
另一个要考虑的事情是你的代码> BIDYALALL 。这真的有必要吗?是否确实要将事件侦听器添加到根的每个最后子级?就目前的情况而言,所需要做的就是将焦点强制回到根目录,并且只使用1个事件侦听器。这可能会在将来为你打破,但不一定
一次移动球1个像素是不明智的。这样做会迫使您依赖于再次调用move函数的速度。这将是不同的,从一台电脑到下一台电脑,你的游戏将永远不会可靠地运行。你的玩家应该有一个移动速度,这个速度应该变小或变大以补偿每秒当前的帧数。这样,无论发生什么,游戏总是以完全相同的速度运行。当fps下降时,它会显得更加起伏,但外观与实际行驶的距离是相同的。如果无论性能如何,所有内容都保持不变,那么所有内容也都是可预测的。想象一个两人玩的多人游戏,一人以每秒60帧的速度运行,另一人以每秒30帧的速度运行。如果第二个人的每件事都移动了一半,你怎么能确定呢
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, width=500, height=400, bd=0, highlightthickness=0)
canvas.pack()
circle = canvas.create_oval(50, 50, 80, 80, fill="yellow")
update_id = None
def update():
global update_id
canvas.move(circle, 0, 5)
#this id gets created whether you use it or not ... so use it.
update_id = root.after(1000//60, update)
root.bind("a", lambda e:root.after_cancel(update_id))
root.focus_force()
update()
root.mainloop()
我想你可以看看这个为什么你要绑定成一个循环?您只需要绑定一次。更值得注意的是,为什么要在函数中转储绑定?用一行换另一行你能得到什么?@Michael Guidry,因为这只是整个游戏的一个简单部分。只是一个观察,但你可以将dir
全部转储,并将after\u cancel
绑定到key命令。@MichaelGuidry使用after\u cancel()
仍然需要存储after()返回的ID
。有关我在评论中提到的内容的完整范围,请参阅我的答案。