【发布时间】:2021-07-14 16:21:45
【问题描述】:
我的用例
我需要知道何时按下并按住(特定)键。检测后的用例相当简单。当按键被释放时,发送一个信号来停止回调(我已经知道了)。
期望的行为
以下是算法外观的粗略方案:
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() 的值使用三个不同的函数)。
你将如何实现它?
EDIT-1
HERE 是我在 Isak 建议后写的尝试(和 MCVE)。这与 just 1 缺陷几乎完美配合。那就是它不会从程序开始就听按键。
由于某种未知原因,它需要一些时间才能真正开始检测到任何按键。好消息是,一旦它第一次检测到按键,它就可以完美运行。
我错过了什么?
【问题讨论】:
标签: python callback keyboard keyboard-events pynput