Clearer
Clearer

Reputation: 2306

Is there an easy way to trigger a hoverenter/hoverleave event on children of a QWidget?

For styling purposes, I'm trying to make all the widgets in a set of widgets adopt a certain background if a pointer enteres any of those widgets; i.e. if the pointer is insides the containing rectangle of widget A, both A and widget B should change its background. Likewise if the pointer enters B, then A should also adopt the same background. The background should, naturally, fall back to the non-hovering background if the pointer is outside both A and B.

QWidget appears to have most of the plumbing to get this done, but its hidden behind protected.

I really want to avoid inheriting from QWidget if I can avoid it and I really would like to not have to change the stylesheets of the widgets too.

[1] In my case, I have three widgets, not two.

Upvotes: 0

Views: 404

Answers (1)

p-a-o-l-o
p-a-o-l-o

Reputation: 10077

Have an event filter class, and let it hold the affected widgets in a vector of pointers:

#include <QMouseEvent>

class EventFilter : public QObject
{
    Q_OBJECT
    QVector<QWidget*> widgets;

public:
    void append(QWidget * w)
    {
        w->setAttribute(Qt::WA_Hover);
        w->installEventFilter(this);
        widgets.append(w);
    }
    bool eventFilter(QObject *watched, QEvent *event)
    {
        if(event->type() == QMouseEvent::HoverEnter)
        {
            for(auto w : widgets)
            {
                w->setStyleSheet("background-color: red;");
            }
        }
        else if(event->type() == QMouseEvent::HoverLeave)
        {
            for(auto w : widgets)
            {
                w->setStyleSheet("background-color: white;");
            }
        }
        return false;
    }
};

The append method will set up the widget and push it in the vector.

Have a private filter instance in your form class:

class Form : public QWidget
{
    Q_OBJECT

    //...

private:
    EventFilter filter;

   //...

In your form constructor:

ui->setupUi(this);

filter.append(ui->widget1);
filter.append(ui->widget2);
filter.append(ui->widget3);

In the example I used setStyleSheet to set the background color, but you can use whatever strategy you prefer, i.e. resetting the widget palette.

Upvotes: 1

Related Questions