Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.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绑定-允许同时按下多个键_Python_Bind_Tkinter_Keyboard Events - Fatal编程技术网

Python绑定-允许同时按下多个键

Python绑定-允许同时按下多个键,python,bind,tkinter,keyboard-events,Python,Bind,Tkinter,Keyboard Events,我在Python中遇到了一个问题 我使用的是Tkinter,有四个绑定事件,可以监听表单上的按键。 我的问题是,这些不是异步运行的。例如,我可以按下一个按钮,事件就会被识别。但当我同时按住两个键时,只会触发一个事件 有没有其他方法可以做到这一点 self.f.bind("w", self.player1Up) self.f.bind("s", self.player1Down) self.f.bind("o", self.player2Up) self.f.bin

我在Python中遇到了一个问题

我使用的是Tkinter,有四个绑定事件,可以监听表单上的按键。 我的问题是,这些不是异步运行的。例如,我可以按下一个按钮,事件就会被识别。但当我同时按住两个键时,只会触发一个事件

有没有其他方法可以做到这一点

    self.f.bind("w", self.player1Up)
    self.f.bind("s", self.player1Down)
    self.f.bind("o", self.player2Up)
    self.f.bind("l", self.player2Down)
您可以绑定到“”,然后检查event.char并根据该值执行所需的操作?当然,我不知道当同时按下多个键时这是否有效,它可能仍然会遇到完全相同的问题。我好久没用Tk了


“用户按了任意键。该键在传递给回调的事件对象的char成员中提供(这是特殊键的空字符串)。”

不幸的是,您在某种程度上受制于系统的底层自动重复机制。例如,在我目前使用的mac电脑上,如果我按住“w”,我将获得一系列新闻发布事件。当按下时,如果我按下“o”,我会看到“o”的一连串按下和释放,但“w”没有更多的事件

您需要设置一个迷你状态机,并绑定到按键和按键释放事件。这将允许您跟踪哪些键被按下,哪些键未被按下。然后,每次你画一个框架,你可以查询机器,看看哪些键被按下,并采取相应的行动

这是我拼凑的一个快速破解。我只在我的mac上测试过它,而且只在python 2.5上测试过。我从来没有真正尝试过成为一个“pythonic”或高效的人。该代码仅用于说明该技术。使用此代码,您可以同时按“w”或“s”和“o”或“l”上下移动两个拨杆

'''Example that demonstrates keeping track of multiple key events'''
from Tkinter import *

class Playfield:
    def __init__(self):
        # this dict keeps track of keys that have been pressed but not
        # released
        self.pressed = {}

        self._create_ui()

    def start(self):
        self._animate()
        self.root.mainloop()

    def _create_ui(self):
        self.root = Tk()
        self.p1label = Label(text="press w, s to move player 1 up, down", 
                             anchor="w")
        self.p2label = Label(text="press o, l to move player 2 up, down", 
                             anchor="w")
        self.canvas = Canvas(width=440, height=440)
        self.canvas.config(scrollregion=(-20, -20, 420, 420))

        self.p1label.pack(side="top", fill="x")
        self.p2label.pack(side="top", fill="x")
        self.canvas.pack(side="top", fill="both", expand="true")

        self.p1 = Paddle(self.canvas, tag="p1", color="red", x=0, y=0)
        self.p2 = Paddle(self.canvas, tag="p2", color="blue", x=400, y=0)

        self._set_bindings()

    def _animate(self):
        if self.pressed["w"]: self.p1.move_up()
        if self.pressed["s"]: self.p1.move_down()
        if self.pressed["o"]: self.p2.move_up()
        if self.pressed["l"]: self.p2.move_down()
        self.p1.redraw()
        self.p2.redraw()
        self.root.after(10, self._animate)

    def _set_bindings(self):
        for char in ["w","s","o", "l"]:
            self.root.bind("<KeyPress-%s>" % char, self._pressed)
            self.root.bind("<KeyRelease-%s>" % char, self._released)
            self.pressed[char] = False

    def _pressed(self, event):
        self.pressed[event.char] = True

    def _released(self, event):
        self.pressed[event.char] = False

class Paddle():
    def __init__(self, canvas, tag, color="red", x=0, y=0):
        self.canvas = canvas
        self.tag = tag
        self.x = x
        self.y = y
        self.color = color
        self.redraw()

    def move_up(self):
        self.y = max(self.y -2, 0)

    def move_down(self):
        self.y = min(self.y + 2, 400)

    def redraw(self):
        x0 = self.x - 10
        x1 = self.x + 10
        y0 = self.y - 20
        y1 = self.y + 20
        self.canvas.delete(self.tag)
        self.canvas.create_rectangle(x0,y0,x1,y1,tags=self.tag, fill=self.color)

if __name__ == "__main__":
    p = Playfield()
    p.start()
“演示跟踪多个关键事件的示例”
从Tkinter进口*
班级操场:
定义初始化(自):
#此记录记录已按下但未按下的键
#释放
self.pressed={}
self.\u创建\u ui()
def启动(自):
self._animate()
self.root.mainloop()
定义创建用户界面(自我):
self.root=Tk()
self.p1label=Label(text=“按w,s向上、向下移动播放器1”,
anchor=“w”)
self.p2label=Label(text=“按o,l向上,向下移动播放器2”,
anchor=“w”)
self.canvas=canvas(宽度=440,高度=440)
self.canvas.config(scrollregion=(-20,-20,420,420))
self.p1label.pack(side=“top”,fill=“x”)
self.p2label.pack(side=“top”,fill=“x”)
self.canvas.pack(side=“top”、fill=“both”、expand=“true”)
self.p1=桨(self.canvas,tag=“p1”,color=“red”,x=0,y=0)
self.p2=桨(self.canvas,tag=“p2”,color=“blue”,x=400,y=0)
self.\u set\u bindings()
def_动画(自):
如果按下self.w[“w”]:self.p1.move_up()
如果按下self.s[“s”]:self.p1.move_down()
如果按下self.o[“o”]:self.p2.move_up()
如果self.pressed[“l”]:self.p2.move_down()
self.p1.redraw()
self.p2.redraw()
self.root.after(10,self.\u动画)
定义集绑定(自):
对于[“w”、“s”、“o”、“l”]中的字符:
self.root.bind(“%char,self.\u按)
self.root.bind(“%char,self.\u已发布)
self.pressed[char]=False
def_按下(自身,事件):
self.pressed[event.char]=True
def_释放(自身、事件):
self.pressed[event.char]=False
类桨():
定义初始化(自我、画布、标签、颜色=“红色”,x=0,y=0):
self.canvas=画布
self.tag=tag
self.x=x
self.y=y
self.color=颜色
self.redraw()
def上移(自):
self.y=max(self.y-2,0)
def向下移动(自):
self.y=min(self.y+2400)
def重绘(自):
x0=self.x-10
x1=自身x+10
y0=自我。y-20
y1=自身y+20
self.canvas.delete(self.tag)
self.canvas.create_矩形(x0,y0,x1,y1,tags=self.tag,fill=self.color)
如果名称=“\uuuuu main\uuuuuuuu”:
p=运动场()
p、 开始()

Tkinter可能不是一个好的游戏环境。您看过PyGame吗?请注意,PyGame还不能用于Python3.x。因此,它目前不是一个通用的Python解决方案,将来可能也不会有太多的选择,除非他们将其移植到Python3.x+。适合2.x.Pyglet和cocos2d可能是pygame的现代替代品。。这看起来有你可能正在寻找的解决方案,但总的来说,我想说切换到PyGame可能是你在这里更好的选择。