检测按键是否按下 - python

问题描述 投票:0回答:3

我的用例

我需要知道何时按下并按住(特定)键。检测后的用例相当简单。当按键被释放时,发送一个信号来停止回调(我已经知道了)。

期望的行为

这是算法的粗略方案:

def the_callback():
    if key_held == the_hotkey:
        someObj.start()  # this class Obj works totally well so no issues here on
    elif key_released == the_hotkey:
        someObj.stop()
    else:
        # we don't care. continue looking for Keyboard events

# here any kinda listener or just a loop which passes events to the callback

我应该提到,任何阻止执行的侦听器都可以,因为它将在自己的线程中运行(已经在线程中运行

pynput.keyboard.Listener
,所以不是问题)

我尝试过的事情

我使用

pynput
及其
pynput.keyboard.Listener
来检测按键并相应地调用回调,但我无法检测按键何时被按下。

当前的解决方案大致如下:

# not real code. just rough scheme
def on_pressed(key):
    if key == my_hotkey:
        if running_already:  # this part works well already
            obj.stop()
        else:
            obj.start()
    else:
        # we don't care

with pynput.keyboard.Listener(on_press=on_pressed) as listener:
    listener.join()  # blocking call until SystemExit, `return False` from callback or `listener.stop()` 
    

我有一种非常强烈的感觉,我可以通过添加

on_release=another_callback_that_handles_releases
(在
pynput.keyboard.listener
内可用)来完成这项工作。

也许通过存储最后一次已知按下的按键,并检查释放的按键是否与之前按下的热键相同,但我不确定如何处理它,这是否可以工作?

然后我决定尝试一下

keyboard
(不同的库)。 我编写了下面的代码,它可以检测按下的按键。下面的代码几乎实现了我想要的:

import keyboard as kb, time

while 1:
    while kb.is_pressed('q'):
        print('Key is held')
        time.sleep(0.5)  # sleep added just to stop it from spamming the stdout
        
    else:
        print('No it\'s Not')
        time.sleep(0.5)

这个解决方案的问题是,它不太适合 OSX 和 Ubuntu。使用特殊键时存在一些问题。此外,我将热键存储为

pynput.keyboard.Key.f7
(例如)或
pynput.keyboard.KeyCode(char='s')  # for character keys
,这些枚举的值与
keyboard
用于扫描密钥 ID 的值不同(使用
keyboard.hook()
)。

最后一个问题

我应该如何检测按键被按下的情况。我更喜欢使用

pynput
来实现这一点,因为代码库的其余部分使用它,但
'keyboard
也很好。 我再次有一种感觉,使用
on_press=a_callback
on_release=another_callback
这可能会实现,但我并不完全确定。最后,解决方案最好是跨平台的(我可以根据
platform.system()
的值使用三个不同的函数)。

你会如何实现它?

编辑-1

这里是我在 Isak 建议后尝试(和 MCVE)写的。这几乎可以完美地工作,只有 1 个缺陷。那就是它不会从程序启动时就监听按键。 由于某种未知原因,它需要一些时间才能开始实际检测任何按键。好处是,一旦它第一次检测到按键,它就可以完美地工作。

我错过了什么?

python callback keyboard keyboard-events pynput
3个回答
2
投票
the key_pressed

事件,直到事件变为

key_released
。因此,当您检测到对该键的点击时,您会执行代码,而当它检测到该键的释放时,代码就会停止
    


1
投票
My Approach

在开始 Listener 之前需要花费大量时间来初始化。这是因为 while 循环没有任何

time.sleep()
调用,并且它可能会扰乱系统(尽管我不希望这种情况发生,因为它在自己的线程中运行,但可能
while
循环不会不要释放
GIL
,因为它只是在循环中,实际上什么也不做,没有任何延迟)。
我刚刚在 while 循环(外部循环)内添加了 

time.sleep(0.2)

。任何延迟都会发生,因为这会释放

GIL
一段时间,并且
Listener
线程将被处理并激活。
编辑:接受 Isak 的答案,因为这是正确的方法。


0
投票

from pynput.keyboard import Key , Listener from pynput import keyboard last_pressed_key = None def on_press(key): global last_pressed_key if last_pressed_key == None and key == Key.f8: last_pressed_key = key print(f"Pressed: {key}") elif key == last_pressed_key: pass def on_release(key): global last_pressed_key if last_pressed_key is not None and key == last_pressed_key: print(f"Released: {key}") last_pressed_key = None # Reset after release else: pass listener = keyboard.Listener(on_press=on_press,on_release=on_release) listener.start() while True: pass

© www.soinside.com 2019 - 2024. All rights reserved.