Important: Please read the Qt Code of Conduct -

Advanced drop-down menu

  • Hey,

    I'd like to realize sth like this:

    The top is a custom toolbar consisting of a bunch of buttons. When hovering over one of them with the mouse pointer, I'd like a drop-down menu to appear below it and disappear as soon as the mouse pointer isn't positioned on either the toolbar button or any part of the drop-down menu anymore. I could do 80% relatively quickly but then ran into a lot of positioning/layout/focus management problems. My code got hackier and really ugly and in the end, I don't know how to cleanly do this. Any suggestions?

  • Have you tried using a QWidgetAction?

  • Not really since my toolbar is not a QToolBar but a custom widget with other stuff and some QToolButtons, so I can't really add actions to it. I anyway don't think this would be enough since I need to customize the entire drop-down menu, not just the widgets/buttons inside of it.

  • You could set a QMenu for your QToolButton and add a QWidgetAction to the QMenu.
    Inside the QWidgetAction you can layout and do evenything you could do in a normal QWidget.
    This includes the use of QLayouts, stylesheets etc.

  • Can I also control the QMenu behavior then and have it appear/disappear on hover and not just on clicking/focus-out? Also what about the gray rectangle in my screenshot that's connecting the QToolButton and the menu? Can I somehow realize this with a built-in QMenu?

  • Well, obvious there is no out of the box solution.
    But you can get a long way with the QWidget::paintEvent.
    And yes, you can have it appear/disappear on hover.
    Take a look at the enterEvent and leaveEvent of your ToolButton.

  • Ok, just to recap: I need to subclass QToolButton and emit the signals for showing/hiding the drop-down in reaction to enter/leave events. Then I have to subclass QMenu and specifically override it's paintEvent to draw the connecting rectangle. Am I then able to do sth like this:

    void QMyMenu::paintEvent() override
      // move to bottom left corner of connector rect
      QMenu::paintEvent();  // draw the rest of the menu by using Qt's default behavior

    The only question left then is where and how to do the positioning because QToolButtons drop-down by default appears below the mouse cursor when clicked but I want everything starting from the tool buttons' bottom left corner. Is it correct doing this inside paintEvent? Will this also set the border rectangles of all drop-down parts correctly?

  • That's how I would do it.
    As for the position, have a look at these:

    QMenu::exec(somewidget.mapToGlobal(QPoint(0, 0)));
    QMenu::popup(somewidget.mapToGlobal(QPoint(0, 0)));

Log in to reply