我有以下代码,
如果我按'左箭头键',它只打印move player to left
但我需要一种功能,按下给定的箭头键可以使玩家沿给定方向移动。
有没有办法可以在move_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()
答案 0 :(得分:2)
如果您想要动画某些内容,则应使用after
设置动画循环。动画循环如下所示:
def animate():
<draw one frame of your animation>
after(<delay>, animate)
您可以放置任何想要绘制框架的代码。在你的情况下,听起来你想要向左或向右移动一些东西。 <delay>
参数定义您的帧速率。例如,要获得30FPS,您的延迟将是大约33(1000ms / 30)。唯一需要注意的重要事项是<draw one from of your animation>
需要非常快速地运行(10毫秒或更短)才能阻止GUI。
对于您的特定问题,您可以设置一个变量来定义用户按下某个键时的方向,然后在释放该键时取消设置该变量。您的事件处理程序和动画函数可能如下所示:
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()
答案 1 :(得分:1)
编辑4
您有一个想要与Tkinter主循环结合的while循环。 在这种情况下,您希望在按下键时移动,并在释放键时停止移动。 下面的代码允许您这样做:
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()
要了解这是如何实现的,您可以阅读源代码或阅读Bryan Oakley的第二个答案。
编辑3
无法直接在move_dir
函数中检测到按键。
您可以在root.update()
函数中使用move_dir
,以便在调用kr
时执行kp
,root.update
。 root.update()
重新绘制窗口,以便用户可以看到更改。
root.mainloop()
可以被视为while True: root.update()