Python Tkinter:长按空格键1秒后调用函数

1 投票
2 回答
2362 浏览
提问于 2025-04-28 11:19

我想为我的图形用户界面(GUI)创建一个功能,使用按键事件。我的目标是:如果用户按住空格键超过1秒钟,就调用一个功能;但如果在这1秒内松开了空格键,就取消这个功能。

我该怎么做呢?

欢迎对我的例子进行修改:

from Tkinter import Tk, Frame

class Application(Frame):

   def __init__(self, parent):
      Frame.__init__(self, parent)
      self.parent = parent
      self.parent.geometry('%dx%d+%d+%d' % (800, 300, 0, 0))
      self.parent.resizable(0, 0)

      self.pack(expand = True)
      self.parent.bind('<Control-s>', self.printer)
   def printer(self, event = None):
      print "Hello World"

def main():
   root = Tk()
   Application(root)
   root.mainloop()

if __name__ == '__main__':
   main()

使用的是Python 2.7,操作系统是Linux

参考链接:http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm

暂无标签

2 个回答

1

我知道这个问题已经很久了,但我通过一些尝试和错误找到了一个解决办法,想把它分享出来,希望能帮助到其他人。(请注意,我只在Python 3.6和Windows上测试过这个方法,不过我在Linux上也有类似的解决方案可以处理长按鼠标按钮,所以我想这个方法应该也适用。)

from tkinter import Tk, Frame

class Application(Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent
        self.parent.geometry('%dx%d+%d+%d' % (800, 300, 0, 0))
        self.parent.resizable(0, 0)

        self.pack(expand = True)
        self._short_press = None
        self.parent.bind('<KeyPress-space>', self.on_press_space)
        self.parent.bind('<KeyRelease-space>', self.on_release_space)

    # set timer for long press
    def on_press_space(self, event):
        if self._short_press is None: # only set timer if a key press is not ongoing
            self._short_press = True
            self._do_space_longpress = self.after(1000, self.do_space_longpress)

    # if it was a short press, cancel event. If it was a long press, event already happened
    def on_release_space(self, event):
        if self._short_press:
            self.cancel_do_space_longpress()

    # do long press action
    def do_space_longpress(self):
        self.cancel_do_space_longpress() # cancel any outstanding timers, if they exist
        print('long press')

    # cancels long press events
    def cancel_do_space_longpress(self):
        self._short_press = None
        if self._do_space_longpress:
            self.parent.after_cancel(self._do_space_longpress)

def main():
    root = Tk()
    Application(root)
    root.mainloop()

if __name__ == '__main__':
    main()
3

这个问题可能很简单,也可能很复杂,具体取决于几个因素。从概念上讲,解决方案是简单的:

  1. 当你按下空格键时,使用 after 来安排一个将来要执行的任务。
  2. 当你松开键时,取消这个任务。

问题的复杂之处在于,有些系统在你按住一个键的时候,会持续自动重复这个按键的动作(这样你会连续收到一连串的按键事件,而不需要松开),或者会发送一对按下和松开的事件(你会收到稳定的按下/松开事件流)。这种情况可能是在键盘硬件层面处理的,也可能是操作系统来处理的。

撰写回答