Python绑定-允许同时按下多个键 [英] Python bind - allow multiple keys to be pressed simultaniously

查看:507
本文介绍了Python绑定-允许同时按下多个键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Python中遇到问题.

I have a problem in Python.

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

I'm using Tkinter and have four bind events, that listen to key presses on my form. My problem is, that these don't run asynchronously. So, for example I can press one button, and the events are recognized. But when I press and hold two keys at the same time, just one event gets fired.

是否有其他方法可以做到这一点?

Is there an alternative way to do this?

    self.f.bind("w", self.player1Up)
    self.f.bind("s", self.player1Down)
    self.f.bind("o", self.player2Up)
    self.f.bind("l", self.player2Down)

推荐答案

不幸的是,您有点受系统底层自动重复机制的影响.例如,在Mac上,如果按住"w"键,我将获得一连串的新闻发布事件.在按下的同时,如果我按下"o",则会得到一连串的新闻,并发布"o"的消息,但不再显示"w"的事件.

Unfortunately, you are somewhat at the mercy of the underlying auto-repeat mechanism of your system. For example, on the mac I'm using at the moment if I press and hold "w" I'll get a stream of press and release events. While pressed, if I press "o" I get a stream of presses and releases for "o" but no more events for "w".

您将需要设置一个迷你状态机,并绑定到按键和按键释放事件.这将使您跟踪哪些按键被按下,哪些按键未被按下.然后,每次绘制框架时,您都可以查询机器以查看按下了哪些键并采取相应的措施.

You will need to set up a mini state machine, and bind to both key press and key release events. This will let you track which keys are pressed and which are not. Then, each time you draw a frame you can query the machine to see which keys are pressed and act accordingly.

这是我一起提出的快速技巧.我仅在我的Mac上进行了测试,并且仅在python 2.5上进行过测试.我没有真正尝试过"pythonic"或高效.该代码仅用于说明该技术.使用此代码,您可以同时按"w"或"s"以及"o"或"l"上下移动两个拨片.

Here's a quick hack I threw together. I've only tested it on my mac, and only with python 2.5. I've made no real attempt at being "pythonic" or efficient. The code merely serves to illustrate the technique. With this code you can simultaneously press either "w" or "s" and "o" or "l" to move two paddles up and down.

'''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()

这篇关于Python绑定-允许同时按下多个键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆