QShortcut on QDesktopWidget disfunctional in PySide2
Unsolved
Qt for Python
-
As I'm currently porting a gui application from Python 2.7.14/PySide 1.2.4 to Python 3.7.1/PySide2 5.11.2 I encountered a problem with the shortcut machinery. Basically:
- Setting
QShortcuts
withQt.ApplicationShortcut
context on theQDesktopWidget
seems disfunctional in PySide2 while working well in PySide.
It seems like other people encountered the same issue too.
- Is this a known bug?
- Is there an elegant workaround for placing application wide shortcuts somewhere in the application without creating an invisible widget for this purpose?
Python 3.7.1/PySide2 5.11.2 (not working)
# -*- coding: utf-8 -*- """Test application wide shortcut on desktop widget fails in PySide2.""" import logging from datetime import datetime from PySide2.QtCore import Qt from PySide2.QtGui import QKeySequence from PySide2.QtWidgets import QShortcut, QWidget, QApplication logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) class Widget(QWidget): """Widget with application wide shortcut.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) shortcut = QShortcut(QKeySequence(Qt.Key_H), QApplication.desktop()) shortcut.setContext(Qt.ApplicationShortcut) shortcut.activated.connect(self.handler) def handler(self): """Shortcut does not trigger.""" msg = f"{datetime.now()}" logger.info(msg) # run app = QApplication() widget = Widget() widget.show() app.exec_()
Python 2.7.14/PySide 1.2.4 (working)
# -*- coding: utf-8 -*- """Test application wide shortcut on desktop widget succeeds in PySide.""" import logging from datetime import datetime from PySide.QtCore import Qt from PySide.QtGui import QKeySequence, QShortcut, QWidget, QApplication logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) class Widget(QWidget): """Widget with application wide shortcut.""" def __init__(self, *args, **kwargs): super(Widget, self).__init__(*args, **kwargs) shortcut = QShortcut(QKeySequence(Qt.Key_H), QApplication.desktop()) shortcut.setContext(Qt.ApplicationShortcut) shortcut.activated.connect(self.handler) def handler(self): """Shortcut does trigger.""" msg = "{}".format(datetime.now()) logger.info(msg) # run app = QApplication(tuple()) widget = Widget() widget.show() app.exec_()
Real use-case
- I have an
ApplicationHotkeyHandler
which is aQObject
that defines all the application wide shortcuts. - The handler functions on that instance are registered as application wide shortcuts on the
QDesktopWidget
, which comes as part of the Qt infrastructure and seems like an elegant and safe way around creating an invisible, artificial widget just for the purpose of holding application shortcuts.
Here's the gist of what it looks like in the application:
class ApplicationHotkeyHandler(QObject): """Define application wide hotkeys and their handlers here. Shortcuts are placed on QDesktopWidget which is an always available part of the Qt infrastructure. Notes: This is a QObject for signals and parenting but not a QWidget as we don't have to display anything, so the handler instance cannot serve as parent for QShortcuts. """ @hotkey(QKeySequence(Qt.CTRL + Qt.Key_Q), context=Qt.ApplicationShortcut,) def quit(self): QApplication.instance().quit() ...
- Setting