Python Tkinter从函数中获取按键事件
我有以下代码 如果我按“左箭头键”,它只打印Python Tkinter从函数中获取按键事件,python,tkinter,Python,Tkinter,我有以下代码 如果我按“左箭头键”,它只打印将播放器向左移动 但是我需要一个功能,在这个功能中,按下给定的箭头键可以将玩家移动到给定的方向。 在我的move\u dir功能中是否有检测按键事件的方法 PS:对python来说相当陌生 import Tkinter as tk move = 1 pos = -1 def move_dir(): global move global pos while move ==1: if pos == 0:
将播放器向左移动
但是我需要一个功能,在这个功能中,按下给定的箭头键可以将玩家移动到给定的方向。
在我的
move\u dir
功能中是否有检测按键事件的方法
PS:对python来说相当陌生
import Tkinter as tk
move = 1
pos = -1
def move_dir():
global move
global pos
while move ==1:
if pos == 0:
print 'move player to left'
elif pos == 1:
print 'move player to right'
elif pos == -1:
print 'stop moving!'
def kr(event):
global move
global pos
global root
if event.keysym == 'Right':
move = 1
pos = 0
move_dir()
print 'right ended'
elif event.keysym == 'Left':
move = 1
pos = 1
move_dir()
print 'left ended'
elif event.keysym == 'Space':
move = 0
move_dir()
elif event.keysym == 'Escape':
root.destroy()
root = tk.Tk()
print( "Press arrow key (Escape key to exit):" )
root.bind_all('<KeyRelease>', kr)
root.mainloop()
将Tkinter作为tk导入
移动=1
位置=-1
def move_dir():
全球行动
全球pos
当move==1时:
如果pos==0:
打印“向左移动播放器”
elif pos==1:
打印“将玩家向右移动”
elif pos==-1:
打印“停止移动!”
def kr(事件):
全球行动
全球pos
全局根
如果event.keysym=='Right':
移动=1
pos=0
move_dir()
打印“右端”
elif event.keysym==‘Left’:
移动=1
位置=1
move_dir()
打印“左端”
elif event.keysym=='Space':
移动=0
move_dir()
elif event.keysym==‘Escape’:
root.destroy()
root=tk.tk()
打印(“按箭头键(退出键):”)
root.bind_all(“”,kr)
root.mainloop()
编辑4
您有一个while循环,希望与Tkinter main循环相结合。
在这种情况下,您希望按键时移动,松开按键时停止移动。
下面的代码允许您执行此操作:
import Tkinter as tk
from guiLoop import guiLoop # https://gist.github.com/niccokunzmann/8673951#file-guiloop-py
direction = 0
pos = 0 # the position should increase and decrease depending on left and right
# I assume pos can be ... -3 -2 -1 0 1 2 3 ...
@guiLoop
def move_dir():
global pos
while True: # edit 1: now looping always
print 'moving', direction
pos = pos + direction
yield 0.5 # move once every 0.5 seconds
def kp(event):
global direction # edit 2
if event.keysym == 'Right':
direction = 1 # right is positive
elif event.keysym == 'Left':
direction = -1
elif event.keysym == 'Space':
direction = 0 # 0 is do not move
elif event.keysym == 'Escape':
root.destroy()
def kr(event):
global direction
direction = 0
root = tk.Tk()
print( "Press arrow key (Escape key to exit):" )
root.bind_all('<KeyPress>', kp)
root.bind_all('<KeyRelease>', kr)
move_dir(root)
root.mainloop()
将Tkinter作为tk导入
从Guilloop导入Guilloop#https://gist.github.com/niccokunzmann/8673951#file-吉卢普
方向=0
pos=0#位置应根据左右而增减
#我想pos可以是-3 -2 -1 0 1 2 3 ...
@吉卢普
def move_dir():
全球pos
虽然为True:#编辑1:现在始终循环
打印“移动”方向
位置=位置+方向
产量0.5#每0.5秒移动一次
def kp(事件):
全局方向#编辑2
如果event.keysym=='Right':
方向=1#右侧为正
elif event.keysym==‘Left’:
方向=-1
elif event.keysym=='Space':
方向=0#0表示不移动
elif event.keysym==‘Escape’:
root.destroy()
def kr(事件):
全球方向
方向=0
root=tk.tk()
打印(“按箭头键(退出键):”)
root.bind_all(“”,kp)
root.bind_all(“”,kr)
移动目录(根目录)
root.mainloop()
要了解这是如何实现的,您可以阅读源代码或阅读Bryan Oakley的第二个答案
编辑3
无法直接在move\u dir
功能中检测按键。
您可以在move_dir
函数中使用root.update()
,以便在调用root.update
时执行kr
,kp
root.update()
还会重新绘制窗口,以便用户可以看到更改
root.mainloop()
可以被视为,而True:root.update()
如果您想要为某个对象设置动画,则应该在之后使用来设置动画循环。动画循环如下所示:
def animate():
<draw one frame of your animation>
after(<delay>, animate)
def animate():
if direction is not None:
print "move player to the ", direction
after(33, animate)
def on_keypress(event):
global direction
if event.keysym == "Left":
direction = "left"
elif event.keysum == "right":
direction = "right"
def on_keyrelease(event):
global direction
direction = None
看到了吗?当你按下一个键时,它定义了方向。然后,每33毫秒检查一次方向,如果确定了方向,则移动播放器。当用户松开按钮时,方向变得不确定,移动停止
把它们放在一起,并使用一个类来避免使用全局变量,它看起来如下所示。这将在画布上创建一个球,可以向左、向右、向上和向下移动:
import Tkinter as tk
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.direction = None
self.canvas = tk.Canvas(width=400, height=400)
self.canvas.pack(fill="both", expand=True)
self.canvas.create_oval(190, 190, 210, 210,
tags=("ball",),
outline="red", fill="red")
self.canvas.bind("<Any-KeyPress>", self.on_press)
self.canvas.bind("<Any-KeyRelease>", self.on_release)
self.canvas.bind("<1>", lambda event: self.canvas.focus_set())
self.animate()
def on_press(self, event):
delta = {
"Right": (1,0),
"Left": (-1, 0),
"Up": (0,-1),
"Down": (0,1)
}
self.direction = delta.get(event.keysym, None)
def on_release(self, event):
self.direction = None
def animate(self):
if self.direction is not None:
self.canvas.move("ball", *self.direction)
self.after(50, self.animate)
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
将Tkinter作为tk导入
类示例(tk.Frame):
定义初始化(自身,父级):
tk.Frame.\uuuu init\uuuuu(自,父)
self.direction=无
self.canvas=tk.canvas(宽度=400,高度=400)
self.canvas.pack(fill=“both”,expand=True)
self.canvas.create_椭圆形(190190210210,
标记=(“球”,),
outline=“red”,fill=“red”)
self.canvas.bind(“,self.on_press)
self.canvas.bind(“,self.on_release)
self.canvas.bind(“,lambda事件:self.canvas.focus\u set())
self.animate()
def on_按下(自身,事件):
增量={
“右”:(1,0),
“左”:(-1,0),
“向上”:(0,-1),
“向下”:(0,1)
}
self.direction=delta.get(event.keysym,None)
def on_释放(自身、事件):
self.direction=无
def动画(自):
如果self.direction不是None:
self.canvas.move(“球”、*self.direction)
self.after(50,self.animate)
如果名称=“\uuuuu main\uuuuuuuu”:
root=tk.tk()
示例(root).pack(fill=“both”,expand=True)
root.mainloop()
谢谢你的回复,但这不是我想要的。让我再次解释一下,如果我按下右键,只要没有按下其他键,我就想向右移动。在您的示例中,它移动一个位置并停止,但我需要保持该位置的增量,直到按空格、左键或Escape键编辑文章。我猜:)又编辑了一次。。更改了move_dir的调用。我创建了Guilloop,以便能够使用while循环和Tkinter。如果您不想使用它,请告诉我。如果您可以与Guilloop一起使用,请告诉我。我会很高兴的。有可能在不使用while循环的情况下通过连续函数调用来实现。感谢您的及时响应。我正在使用guiLoop,但我也想知道其他的可能性。每当我在GUI程序中看到无限循环时,我的蜘蛛就会感到刺痛。即使你有收益,我认为有更好的方法来完成同样的事情。谢谢布莱恩。我认为问题的方向不同。我必须用箭头键控制步进电机,而不是移动播放器
。所以,左
或右
键的行程可以让我的马达在那个方向移动