如何在 PyQt5 中使用全局键盘快捷键显示 QMenu?
How to show a QMenu using global keyboard shortcut in PyQt5?
我试图通过 PyQt5 通过热键(例如 "F1")显示 QMenu 实例,然后我找到了这个包 keyboard。
尝试像这样使用它:keyboard.add_hotkey('F1', self.show_menu, suppress=True)
然后我得到了这些代码:
import sys
import keyboard
from PyQt5.QtCore import Qt
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__(flags=Qt.WindowStaysOnTopHint)
self.menu = QMenu('Menu')
self.menu.addAction(QAction('menu1', self.menu))
self.menu.addAction(QAction('menu2', self.menu))
self.menu.addAction(QAction('menu3', self.menu))
self.show_menu() # this works well
keyboard.add_hotkey('F1', self.show_menu, suppress=True) # this hotkey works but not showing the menu
def show_menu(self):
print('111')
self.menu.popup(QCursor().pos())
print('222')
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(False)
win = MainWindow()
# win.show()
sys.exit(app.exec_())
实际上,在__init__
中调用方法self.show_menu
效果很好,可以按预期弹出菜单。
但是 问题 是,当我按下热键 "F1" 时,会打印“111”和“222”,但不会打印菜单出现。
有什么不对的地方吗,或者我可以通过其他方式实现吗?请告诉我,谢谢。
与add_hotkey关联的回调在辅助线程中执行,在OP代码中回调是修改Qt禁止的GUI的show_menu方法。解决方案是使用信号:
import sys
import keyboard
from PyQt5.QtCore import Qt, QObject, pyqtSignal
from PyQt5.QtGui import QCursor
from PyQt5.QtWidgets import QAction, QApplication, QMainWindow, QMenu
class KeyBoardManager(QObject):
F1Signal = pyqtSignal()
def start(self):
keyboard.add_hotkey("F1", self.F1Signal.emit, suppress=True)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__(flags=Qt.WindowStaysOnTopHint)
self.menu = QMenu("Menu")
self.menu.addAction(QAction("menu1", self.menu))
self.menu.addAction(QAction("menu2", self.menu))
self.menu.addAction(QAction("menu3", self.menu))
manager = KeyBoardManager(self)
manager.F1Signal.connect(self.show_menu)
manager.start()
def show_menu(self):
print("111")
self.menu.popup(QCursor.pos())
print("222")
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(False)
win = MainWindow()
# win.show()
sys.exit(app.exec_())
我试图通过 PyQt5 通过热键(例如 "F1")显示 QMenu 实例,然后我找到了这个包 keyboard。
尝试像这样使用它:keyboard.add_hotkey('F1', self.show_menu, suppress=True)
然后我得到了这些代码:
import sys
import keyboard
from PyQt5.QtCore import Qt
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__(flags=Qt.WindowStaysOnTopHint)
self.menu = QMenu('Menu')
self.menu.addAction(QAction('menu1', self.menu))
self.menu.addAction(QAction('menu2', self.menu))
self.menu.addAction(QAction('menu3', self.menu))
self.show_menu() # this works well
keyboard.add_hotkey('F1', self.show_menu, suppress=True) # this hotkey works but not showing the menu
def show_menu(self):
print('111')
self.menu.popup(QCursor().pos())
print('222')
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(False)
win = MainWindow()
# win.show()
sys.exit(app.exec_())
实际上,在__init__
中调用方法self.show_menu
效果很好,可以按预期弹出菜单。
但是 问题 是,当我按下热键 "F1" 时,会打印“111”和“222”,但不会打印菜单出现。
有什么不对的地方吗,或者我可以通过其他方式实现吗?请告诉我,谢谢。
与add_hotkey关联的回调在辅助线程中执行,在OP代码中回调是修改Qt禁止的GUI的show_menu方法。解决方案是使用信号:
import sys
import keyboard
from PyQt5.QtCore import Qt, QObject, pyqtSignal
from PyQt5.QtGui import QCursor
from PyQt5.QtWidgets import QAction, QApplication, QMainWindow, QMenu
class KeyBoardManager(QObject):
F1Signal = pyqtSignal()
def start(self):
keyboard.add_hotkey("F1", self.F1Signal.emit, suppress=True)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__(flags=Qt.WindowStaysOnTopHint)
self.menu = QMenu("Menu")
self.menu.addAction(QAction("menu1", self.menu))
self.menu.addAction(QAction("menu2", self.menu))
self.menu.addAction(QAction("menu3", self.menu))
manager = KeyBoardManager(self)
manager.F1Signal.connect(self.show_menu)
manager.start()
def show_menu(self):
print("111")
self.menu.popup(QCursor.pos())
print("222")
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(False)
win = MainWindow()
# win.show()
sys.exit(app.exec_())