简体   繁体   English

检测 PyQt5 中的外部键盘事件

[英]Detect external keyboard events in PyQt5

How can I implement a key listener in PyQT5?如何在 PyQT5 中实现关键侦听器? I want to detect keypresses even when the app is in background.即使应用程序在后台,我也想检测按键。

from PyQt5 import QtGui
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
import sys


class Window(QWidget):
    
    ...
       

    def keyPressEvent(self, e): # doesnt work when app is in background
        if e.key() == Qt.Key_F3:
            print(1)
        elif e.key() == Qt.Key_F4:
            print(0)

   ...

        
App = QApplication(sys.argv)
App.setStyle('Fusion')
window = Window()
sys.exit(App.exec())


Qt can access keyboard events only if any of its top level window has keyboard focus. Qt 只有在其任何顶级 window 具有键盘焦点时才能访问键盘事件。 If the window is minimized or another window takes focus, you will not receive keyboard events.如果 window 被最小化或另一个 window 获得焦点,您将不会收到键盘事件。

The only solution is to use an external library, but they have limitations.唯一的解决方案是使用外部库,但它们有局限性。

The keyboard module does not seem to support macOS, while pyinput does, but requires root access for that OS.键盘模块似乎不支持 macOS,而pyinput支持,但需要该操作系统的 root 访问权限。 I don't know of any other ways that support all three platforms without limitations.我不知道有任何其他方式可以不受限制地支持所有三个平台。

In any case, you should not rely on timed checking of the currently pressed keys, because you'll certainly end up missing some events.在任何情况下,您都不应该依赖对当前按键的定时检查,因为您最终肯定会错过一些事件。
While normally one would use a separate thread that implements the event listener (which are normally blocking), luckily in both cases there are non blocking systems to call callback functions (so you don't actually need a separate thread).虽然通常会使用一个单独的线程来实现事件侦听器(通常是阻塞的),但幸运的是,在这两种情况下都有非阻塞系统来调用回调函数(因此您实际上不需要单独的线程)。

The following is a basic example using the keyboard module:以下是使用keyboard模块的基本示例:

from PyQt5 import QtCore, QtWidgets
import keyboard

class KeyGrabber(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        layout = QtWidgets.QVBoxLayout(self)
        self.button = QtWidgets.QPushButton('start')
        layout.addWidget(self.button)
        self.button.setCheckable(True)
        self.button.toggled.connect(self.setGrabbing)

    def keyboardEventReceived(self, event):
        if event.event_type == 'down':
            if event.name == 'f3':
                print('F3 pressed')
            elif event.name == 'f4':
                print('F4 pressed')

    def setGrabbing(self, enable):
        if enable:
            self.button.setText('stop')
            # on_press returns a hook that can be used to "disconnect" the callback
            # function later, if required
            self.hook = keyboard.on_press(self.keyboardEventReceived)
            self.showMinimized()
        else:
            self.button.setText('start')
            keyboard.unhook(self.hook)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM