2016-11-08 146 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