sidewinderguy
sidewinderguy

Reputation: 2404

Respond to application-wide "hotkey" in Qt

I've got a simple Qt app, and I just want to respond to the F12 key, regardless of which widget has focus.

Is there some easy signal or something I can hook in to?

I want to use the F12 key to toggle the main window fullscreen on/off.

Upvotes: 27

Views: 12116

Answers (4)

Huey Yeng
Huey Yeng

Reputation: 1

Based on HiFile.app answer but tested working for PySide6 on Python 3.11 (and should be applicable for PySide2 but not tested). You will need to subclass QApplication and override the notify function.

class Application(QApplication):
    def notify(self, receiver: QObject, event: QEvent) -> bool:
        if event.type() == QEvent.Type.KeyPress:
            key_event = QKeyEvent(event)
            # Check if key event matches the desire shortcut key
            if key_event.key() == Qt.Key.Key_F12:
                # Do what you want here like toggling fullscreen mode
                return True  # Important! Need to return True for this to work

        return super().notify(receiver, event)

Upvotes: 0

Setting the shortcut context to Qt::ApplicationShortcut has a serious flaw. It will not work in modal dialogs. So if you want a trully real pan-application-wide shortcut, then you need to override application's notify() method. The alternative is to install event filter for the application object but that I suspect would be slower and requires slightly more code. With notify() it is very simple:

class MyApplication : public QApplication
{
    // TODO: constructor etc.

protected:

bool MyApplication::notify(QObject *receiver, QEvent *event) override
{
    if (event->type() == QEvent::KeyPress)
    {
        auto keyEvent = static_cast<QKeyEvent*>(event);
        if (keyEvent->key() == Qt::Key_F12 && keyEvent->modifiers() == Qt::NoModifiers)
        {
            // TODO: do what you need to do
            return true;
        }  
    }
    return QApplication::notify(receiver, event);
}

}

Upvotes: 5

Prof
Prof

Reputation: 706

If you have a "central widget" which all of the other widgets are children of, then you can simply set that as the widget argument for QShortcut.

(Python, qt5)

self.centralwidget = QtWidgets.QWidget(MainWindow)

QtWidgets.QShortcut(QtGui.QKeySequence("F12"), self.centralwidget, self.goFullScreen)

I added this as an answer because the shortcut context flag: Qt.ApplicationShortcut did not work for me.

Upvotes: 2

J&#233;r&#244;me
J&#233;r&#244;me

Reputation: 27027

I haven't tried, but here is what I would do :

Create a QShortcut and make sure its context (with setContext()) is Qt::ApplicationShortcut.

shortcut = new QShortcut(QKeySequence(Qt::Key_F12), parent);
shortcut->setContext(Qt::ApplicationShortcut);

Then you just need to connect a slot to the QShortcut::activated() signal.

Upvotes: 32

Related Questions