Qt World Summit: Register Today!

[SOLVED] How do I clear hover state on a QGraphicsWidget wrapped QToolButton?

  • The scenario is as follows: I have a QGraphicsView with a QGLWidget as viewport. I create a “toolbar” (QFrame), add a layout and several QToolButtons. The toolbar widget is then added to a QGraphicsScene with QGraphicsScene ::addWidget.

    This works reasonably well, mouse over and any other mouse interaction with the buttons works as expected. But several of the buttons have actions that require the toolbar to be hidden. I call QGraphicsWidget:: setVisible to show and hide the toolbar as needed.

    The problem is that when I hide the toolbar as a result of clicking a button in the toolbar when it is shown again the button is still drawn in a hover state even though the mouse isn’t over the button. The only way to clear this is to move to mouse inside the toolbar to force an update of the hover state. But any attempt to force this update through code has failed and I don’t understand how I can force the QToolButton to update its hover state when the toolbar is shown.

    I’ve tried setting cache mode to QGraphicsItem::NoCache, tried calling update(), tried posting MouseLeave and MouseMove events… but nothing works. Tracing the buttons states using QToolButton::initStyleOption after showing the toolbox shows that QStyle::State_MouseOver is set for the button so it is drawn correctly in its hover state.

    What I need is a way to force the button to update its state and at the same time ensure the QGraphicsWidget shape is updated to reflect the change.

    Any idea how I can get this to work?

  • It might be a good idea to subclass your QToolButton and override the enterEvent() and leaveEvent() to tell whether or not your really getting what you see.

    Also, are you changing the look of the button via stylesheets?

  • Good point about tracing button widget leave and enter. Will test do that also to see what's going on.

    And yes I do use a local style sheet, but it behaves the same if I remove the stylesheet so that shouldn't be the problem. But I'll test with all app level style sheets disabled to see if that has any effect.

    I finally got it working in what feels like a rather hackish way...

    I ended up manually checking and updating the mouse over state of all QToolButtons in the toolbar every time the toolbar graphics widget is shown. My first idea with sending leave and enter events ended up working, not entirely sure why it didn't work the first time around but now it does work.

    bool show = ...;
    if (toolbar_->isVisible() != show) {
    if (show) {
    QList<QToolButton*> children = toolbar_->findChildren<QToolButton*>();
    foreach(QToolButton* button, children) {
    QPoint cursor = QCursor::pos();
    // parent_ is the QGraphicsView
    cursor = parent_->mapFromGlobal(cursor);
    cursor -= toolbar_->geometry().topLeft();
    bool inside = button->geometry().contains(cursor);

                if (!inside && button->underMouse()) {
                    QEvent* leaveEvent = new QEvent(QEvent::Leave);
                    QApplication::sendEvent(button, leaveEvent);
                else if (inside && !button->underMouse()) {
                    QEvent* enterEvent = new QEvent(QEvent::Enter);
                    QApplication::sendEvent(button, enterEvent);


Log in to reply