2016-11-08 115 views
2

我可以用Python一些输入法尝试,并使用pynput我已经按下并释放钥匙简单的采集卡,就像在文档:有没有办法在Python中捕获按键,并过滤掉按键重复生成的按键?

from pynput.keyboard import Key, Listener 

def on_press(key): 
    print('{0} pressed'.format(
     key)) 

def on_release(key): 
    print('{0} release'.format(
     key)) 
    if key == Key.esc: 
     # Stop listener 
     return False 

# Collect events until released 
with Listener(
     on_press=on_press, 
     on_release=on_release) as listener: 
    listener.join() 

然而,on_press被称为不管是否键是通过按键重复生成的,或者只是被按下的键,据我所知,我不知道它是哪一个。

有没有办法知道?我的目标平台是macOS,但这应该有望在Windows上工作,以及我可能希望在某一天移植此想法。

pynput很好,但我不介意切换库,如果这意味着我可以得到我需要的工作。

回答

1

在额外的按键事件产生的/不介入键释放事件模拟按键重复事件(至少在我的Ubuntu系统)的情况下:

$ python keypress_vs_repeat.py 
Key.enter release 
a'a' pressed 
a'a' pressed 
a'a' pressed 
a'a' pressed 
a'a' release 

您可以使用这些信息来区分真正的按键从模拟按键:

keypress_vs_repeat.py

from pynput.keyboard import Key, Listener 

currently_pressed_key = None 

def on_press(key): 
    global currently_pressed_key 
    if key == currently_pressed_key: 
     print('{0} repeated'.format(key)) 
    else: 
     print('{0} pressed'.format(key)) 
     currently_pressed_key = key 

def on_release(key): 
    global currently_pressed_key 
    print('{0} release'.format(key)) 
    currently_pressed_key = None 
    if key == Key.esc: 
     # Stop listener 
     return False 

# Collect events until released 
with Listener(
     on_press=on_press, 
     on_release=on_release) as listener: 
    listener.join() 

测试(按一个一次,按住b):

$ python keypress_vs_repeat.py 
Key.enter release 
'a' pressed 
a'a' release 
'b' pressed 
b'b' repeated 
b'b' repeated 
b'b' repeated 
b'b' repeated 
b'b' repeated 
b'b' release 
Key.esc pressed 
^[Key.esc release 
^[$ 
0

这适用于OS X和薄荷。我没有Windows测试:

class _Getch: 
    """Gets a single character from standard input. Does not echo to the 
screen.""" 
    def __init__(self): 
     try: 
      self.impl = _GetchWindows() 
     except ImportError: 
      self.impl = _GetchUnix() 
    def __call__(self): return self.impl() 

class _GetchUnix: 
    def __init__(self): 
     import tty, sys 

    def __call__(self): 
     import sys, tty, termios 
     fd = sys.stdin.fileno() 
     old_settings = termios.tcgetattr(fd) 
     try: 
      tty.setraw(sys.stdin.fileno()) 
      ch = sys.stdin.read(1) 
     finally: 
      termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 
     return ch 

class _GetchWindows: 
    def __init__(self): 
     import msvcrt 

    def __call__(self): 
     import msvcrt 
     return msvcrt.getch() 

getch = _Getch() 

测试:

c=getch() 
i=1 
while c!='q': 
    c=getch() 
    print c, i 
    # if key is held, it does not repeat... 
    i+=1 

基于this ActiveState recipe