Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python tkinter can'中的画布;不能通过按键功能进行更改_Python_Python 3.x_Tkinter - Fatal编程技术网

Python tkinter can'中的画布;不能通过按键功能进行更改

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

我正在学习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")

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
。有关我在评论中提到的内容的完整范围,请参阅我的答案。