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