Qt - Disable/enable all shortcuts

2019-08-27 17:35发布

问题:

I have a Qt 5 application with a 3D viewport which the user can navigate around when holding RClick and using WASDQE. I'd like to make it so holding Ctrl slows the camera movement down, however doing this will activate shortcuts.

Is it possible to disable and enable all shortcuts such that I can disable them while mouse buttons are down?

I've tried installing an event filter onto my main window however shortcuts are still activated (Despite even returning true for every event type).

回答1:

I ended up creating an event filter for my 3D viewport widget to check for mouse presses. Each time I encounter these events (As well as key release events) I then call a function (checkShortcutsEnabled()) on my main window to switch the shortcut content depending on if no buttons are pressed or not.

The reason why I also check for key release events is to only re-enable shortcuts when no keyboard modifiers are held down (Such that if you release your mouse buttons before keyboard keys, you don't accidentally trip a shortcut)

Shortcuts default to Qt::WindowShortcut, meaning they can be activated anywhere in the window. When mouse buttons are down over the viewport, I switch this tempoararily to Qt::WidgetShortcut, which only means they can be activated if the widget received the shortcuts (But not the viewport widget, which is a child of my main window). It's a nicer alternative to disabling/re-enabling them as I don't have to tinker around with saving disabled state, as well as toolbar buttons going grey.

The main window class

    class StageEditorWindow : public QMainWindow {
        Q_OBJECT

        friend class ViewportEventFilter;

        protected:
            /**
             * @brief Checks if any mouse buttons are down and disables/enables shortcuts appropriately
             */
            void checkShortcutsEnabled() {
                QList<QAction*> actions = findChildren<QAction*>();

                if (QApplication::mouseButtons() != Qt::NoButton) {
                    for (QAction *a : actions) a->setShortcutContext(Qt::WidgetShortcut);
                } else if (QApplication::keyboardModifiers() == Qt::NoModifier) {
                    //Don't re-enable shortcuts until modifers have been released
                    for (QAction *a : actions) a->setShortcutContext(Qt::WindowShortcut);
                }
            }

        //Don't forget to install the event filter in your constructor

    };

The event filter class

    /**
     * @brief Used to check if the mouse is pressed over the viewport and disable shortcuts if so
     */
    class ViewportEventFilter : public QObject {
        Q_OBJECT

        private:
            StageEditorWindow *w;

        public:
            ViewportEventFilter(StageEditorWindow *w, QObject *parent = nullptr) :
                QObject(parent),
                w(w) {}

        protected:
            bool eventFilter(QObject *watched, QEvent *event) {
                if (event->type() == QEvent::MouseButtonPress ||
                        event->type() == QEvent::MouseButtonRelease ||
                        event->type() == QEvent::KeyRelease) {
                    w->checkShortcutsEnabled();
                }

                return QObject::eventFilter(watched, event);
            }
    };