How to focus menuBar() with Qt

白昼怎懂夜的黑 提交于 2019-12-20 03:30:11

问题


I have a working application. I added a menuBar() to the main window with some menus. Then, I hid it to free screen space. I wrote the code below so that when user presses ALT key, the menu bar appears if it's hidden, and it hides if it's displayed.

void MainWindow::keyPressEvent( QKeyEvent *k ) {
    if(k->modifiers() & Qt::AltModifier) {
        menuBar()->setHidden(!menuBar()->isHidden());
        if(menuBar()->hasFocus()) {
            QMessageBox::information(this, "Info", "Focus !");
        }
    }
}

As you can see, I also added a QMessageBox to see when the menuBar has the focus. And this box appears only half of the time. It goes like this :

  1. Application launched, menubar hidden
  2. I press ALT, menubar displayed, no message box, no focus
  3. I press ALT, menubar hidden
  4. I press ALT, menubar displayed, message box, focus
  5. I press ALT, menubar hidden
  6. I press ALT, menubar displayed, no message box, no focus
  7. I press ALT, menubar hidden
  8. I press ALT, menubar displayed, message box, focus
  9. etc.

How to make sure when the menuBar is displayed, it always has focus ?


回答1:


I wanted to do the same thing. My solution, complete example, as a gist:

https://gist.github.com/xim/ee56564f425151ea2fa70f730d644873

Tested against Qt 5.9.4.

As it contains a lot of other junk, a minimal example:

class AutoHidingMenuBar : public QMenuBar {
    Q_OBJECT

public:
    AutoHidingMenuBar() : QMenuBar() {
        setMaximumHeight(0);
        connect(qApp, &QApplication::focusChanged, this, &AutoHidingMenuBar::focusChanged);
    }

private slots:
    void focusChanged(QWidget *from, QWidget *to) {
        bool inFocus = hasFocus() || isAncestorOf(focus) || hasFocusedChild();
        if (inFocus && maximumHeight() == 0) {
            auto action = activeAction();
            setMaximumHeight(100);
            if (action) {
                // XXX This is a bit of a hack. We could do
                //   QCoreApplication::processEvents();
                //   setActiveAction(action);
                // with almost the same effect, but then we *open* the first menu on single alt press...
                auto evt = new QMouseEvent(QEvent::MouseMove, actionGeometry(action).center(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
                QCoreApplication::postEvent(this, evt);
            }
        } else if (!inFocus && maximumHeight() != 0)) {
            setMaximumHeight(0);
        }
    }

private:
    bool hasFocusedChild() {
        QObjectList queue{children()};
        while (!queue.empty()) {
            auto child = queue.takeFirst();
            auto widget = dynamic_cast<QWidget *>(child);
            if (widget && widget->hasFocus())
                return true;

            queue.append(child->children());
        }
        return false;
    }
};



回答2:


Have you tried just adding the setFocus command?

void MainWindow::keyPressEvent( QKeyEvent *k ) {
    if(k->modifiers() & Qt::AltModifier) {
        menuBar()->setHidden(!menuBar()->isHidden());
        menuBar()->setFocus(Qt::MenuBarFocusReason);
        if(menuBar()->hasFocus()) {
            QMessageBox::information(this, "Info", "Focus !");
        }
    }
}


来源:https://stackoverflow.com/questions/27928937/how-to-focus-menubar-with-qt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!