【问题标题】:Detect external keyboard events in PyQt5在 PyQt5 中检测外部键盘事件
【发布时间】:2020-07-31 14:01:36
【问题描述】:

如何在 PyQT5 中实现关键监听器?即使应用在后台,我也想检测按键。

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())


【问题讨论】:

  • 仅对具有键盘焦点的小部件(包括顶级窗口)处理键盘事件。你不能从普通的 PyQt 做到这一点,根据你使用的操作系统有不同的解决方案,你可能需要查看 pypi.python.org/pypi/keyboardpypi.org/project/pynput。请注意,两者都需要一个单独的 QThread 子类,因为它们在自己的“事件循环”上运行以等待事件。
  • 你能给我一个例子,它应该如何使用键盘库来完成?我如何在课堂上使用keyboard.is_pressed?
  • 你打算为什么操作系统做这个?因为keyboard 模块在Linux 上需要root 访问权限(并且似乎不支持MacOS),而pyinput 在所有三个平台上都可以工作,但在MacOS 上需要root 访问权限。
  • 在 Windows PC 上。

标签: python pyqt5 keyboard-events keylogger


【解决方案1】:

只有当它的任何顶级窗口具有键盘焦点时,Qt 才能访问键盘事件。如果窗口被最小化或另一个窗口获得焦点,您将不会收到键盘事件。

唯一的解决方案是使用外部库,但它们有局限性。

keyboard 模块似乎不支持 macOS,而 pyinput 支持,但需要该操作系统的 root 访问权限。我不知道有任何其他方法可以不受限制地支持所有三个平台。

在任何情况下,您都不应该依赖对当前按键的定时检查,因为您最终肯定会错过一些事件。
虽然通常会使用一个单独的线程来实现事件侦听器(通常是阻塞的),但幸运的是在这两种情况下都有非阻塞系统来调用回调函数(因此您实际上不需要单独的线程)。

以下是使用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)

【讨论】:

    猜你喜欢
    • 2017-04-06
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 2014-06-22
    • 2016-12-23
    • 1970-01-01
    • 2011-07-16
    • 1970-01-01
    相关资源
    最近更新 更多