Qt PySide2实现全局热键(原生)

Qt PySide2实现全局热键(原生)

全局热键,指无论你的Qt程序有焦点还是最小化到托盘,热键都能响应,这就需要通过原生系统API来实现(本篇文章只实现了window系统)

创建一个系统托盘程序

class TrayIcon(QtWidgets.QWidget):
    def __init__(self) -> None:
        super().__init__()
        self.setupUi()
        self.installEventFilter(self)

    def setupUi(self):
        self.trayIcon = QtWidgets.QSystemTrayIcon()
        # 图标下载网站 https://www.iconfont.cn/
        self.icon = QtGui.QIcon("some.png")
        self.trayIcon.setIcon(self.icon)
        self.trayIcon.show()
        self.trayMenu = QtWidgets.QMenu()
        self.trayExit = QtWidgets.QAction()
        self.trayExit.triggered.connect(lambda : self.close())
        self.trayMenu.addAction(self.trayExit)

        self.trayIcon.setContextMenu(self.trayMenu)

        self.retranslateUi()

    def retranslateUi(self):
        self.trayExit.setText(QtCore.QCoreApplication.translate("Notes", '退出', None))

创建nativeEventFilter

class NativeEvent(QtCore.QAbstractNativeEventFilter):
    def __init__(self):
        super().__init__()

    def nativeEventFilter(self, eventType, message):
        from ctypes import wintypes
        msg = wintypes.MSG.from_address(message.__int__())
        if eventType == 'windows_generic_MSG' and msg.message == win32con.WM_HOTKEY:
            print("hot key pressed")
        return False, 0

注册热键和注销热键

hotkey_id = 1
# 键码对照 https://learn.microsoft.com/zh-cn/windows/win32/inputdev/virtual-key-codes
hotkey_vk = 0x50

hotkey_fsModifiers = win32con.MOD_ALT
user32 = ctypes.windll.user32
def register_hotkey():
    # 注册 Alt+P 热键
    # 函数解释 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-registerhotkey?redirectedfrom=MSDN
    success = user32.RegisterHotKey(None, hotkey_id, hotkey_fsModifiers, hotkey_vk)
    if not success:
        print("热键注册失败")

def unregister_hotkey():
    success = user32.UnregisterHotKey(None, hotkey_id)

main

def main():
    try:
        app = QtWidgets.QApplication()
        # app.setQuitOnLastWindowClosed(False)
        widget = TrayIcon()
        # widget.show()
        nativeEvent = NativeEvent()
        app.installNativeEventFilter(nativeEvent)
        register_hotkey()
        app.exec_()
    # except:
    #     print('except')
    finally:
        unregister_hotkey()

if __name__ == '__main__':
    main()

附完整代码

import ctypes
from PySide2 import QtCore
from PySide2 import QtGui
from PySide2 import QtWidgets

import win32con

class TrayIcon(QtWidgets.QWidget):
    def __init__(self) -> None:
        super().__init__()
        self.setupUi()
        self.installEventFilter(self)

    def setupUi(self):
        self.trayIcon = QtWidgets.QSystemTrayIcon()
        # 图标下载网站 https://www.iconfont.cn/
        self.icon = QtGui.QIcon("some.png")
        self.trayIcon.setIcon(self.icon)
        self.trayIcon.show()
        self.trayMenu = QtWidgets.QMenu()
        self.trayExit = QtWidgets.QAction()
        self.trayExit.triggered.connect(lambda : self.close())
        self.trayMenu.addAction(self.trayExit)

        self.trayIcon.setContextMenu(self.trayMenu)

        self.retranslateUi()

    def retranslateUi(self):
        self.trayExit.setText(QtCore.QCoreApplication.translate("Notes", '退出', None))

class NativeEvent(QtCore.QAbstractNativeEventFilter):
    def __init__(self):
        super().__init__()

    def nativeEventFilter(self, eventType, message):
        from ctypes import wintypes
        msg = wintypes.MSG.from_address(message.__int__())
        if eventType == 'windows_generic_MSG' and msg.message == win32con.WM_HOTKEY:
            print("hot key pressed")
        return False, 0

hotkey_id = 1
# 键码对照 https://learn.microsoft.com/zh-cn/windows/win32/inputdev/virtual-key-codes
hotkey_vk = 0x50

hotkey_fsModifiers = win32con.MOD_ALT
user32 = ctypes.windll.user32
def register_hotkey():
    # 注册 Alt+P 热键
    # 函数解释 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-registerhotkey?redirectedfrom=MSDN
    success = user32.RegisterHotKey(None, hotkey_id, hotkey_fsModifiers, hotkey_vk)
    if not success:
        print("热键注册失败")

def unregister_hotkey():
    success = user32.UnregisterHotKey(None, hotkey_id)

def main():
    try:
        app = QtWidgets.QApplication()
        # app.setQuitOnLastWindowClosed(False)
        widget = TrayIcon()
        # widget.show()
        nativeEvent = NativeEvent()
        app.installNativeEventFilter(nativeEvent)
        register_hotkey()
        app.exec_()
    # except:
    #     print('except')
    finally:
        unregister_hotkey()

if __name__ == '__main__':
    main()

参考:
xxxxGPT
https://blog.csdn.net/m0_60259116/article/details/128631482

你可能感兴趣的:(qt,python,pyside)