0
votes

I have a parent widget inside which I have to place a custom widget (say a QFrame). Inside that custom widget, I have to place a number of child widgets (derived from QPushButton). I want the child widgets to have a certain background under normal circumstances, and another one when hovered upon. This is my code:

//parent widget code, where the QFrame derived widget is initialized
QFrameDerivedWidget *qFrameWidget = new QFrameDerivedWidget(this, someString);

This is the QFrameDerivedWidget header file:

//QFrameDerivedWidget header file
class QFrameDerivedWidget: public QFrame
{
    Q_OBJECT

public:
    QFrameDerivedWidget(QWidget *aParent,
                         std::string someValue);
    bool eventFilter(QObject *obj, QEvent *event);
}

This is the QFrameDerivedWidget implementation file, the ChildWidget class is defined and declared inline:

class ChildWidget: public QPushButton
{
Q_Object
public:
    ChildWidget(std::string aText, QWidget *aParent);

};

ChildWidget::ChildWidget(std::string aText, QWidget *aParent):
                               QPushButton(QString::fromStdString(aText),aParent)
{
    this->setFixedHeight(30);
    this->setMouseTracking(true);
    this->setCursor(Qt::PointingHandCursor);
    /* ---other custom styling--- */
}

bool QFrameDerivedWidget::eventFilter(QObject *obj, QEvent *event)
{
    // this never prints out anything, even though it should for any mouseenter, mouseleave, click, etc event on it
    qDebug() << obj->metaObject()->className() << endl;

    if (obj->metaObject()->className() == "ChildWidget")
    {
        //including this line throws a 'missing QObject missing macro error' as well
        ChildWidget *option = qobject_cast<ChildWidget* >(obj);
        if (event->type() == QEvent::Enter)
        {
            option->setStyleSheet("---");

        }
        if (event->type() == QEvent::Leave)
        {
            option->setStyleSheet("---");
        }
        return QWidget::eventFilter(obj, event);
    }
    else
    {
        // pass the event on to the parent class
        return QWidget::eventFilter(obj, event);
    }
}

QFrameDerivedWidget::QFrameDerivedWidget(QWidget *aParent,
                     std::string someVal): fParent(aParent)
{
    initUI();
}

QFrameDerivedWidget::initUI()
{
    this->setParent(fParent);
    this->setAttribute(Qt::WA_Hover);
    this->setMouseTracking(true);
    QWidget *dd = new QWidget(this);
    QVBoxLayout *layout = new QVBoxLayout();
    dd->setLayout(layout);
    for (int i = 0; i < fValues.size(); i++)
    {
        ChildWidget *button = new ChildWidget(fValues[i],dd);
        button->addEventFilter(this);
        layout->addWidget(button);
    }
}

The idea is, whenever I hover over the QFrameDerivedWidget and enter any ChildWidget, its background color should change. Additionally, I have set a qDebug() statement inside the eventFilter. It is currently not working, the ChildWidget buttons are not visible, but they are there, for the cursor turns pointer when I hover over where they are supposed to be.

What am I doing wrong, and how do I make it work?

1
obj->metaObject()->className() == "ChildWidget" may be replaced with qobject_cast<ChildWidget *>(obj) != nullptrDmitry Sazonov

1 Answers

2
votes
  1. You forget to add Q_OBJECT macro in ChildWidget declaration
  2. You need to track mouse (setMouseTracking(true))
  3. You need to set setAttribute(Qt::WA_Hover) to your widget
  4. Be sure that you really need to return true; in your event filter, instead of returning QWidget::eventFilter(obj, event);. You don't need to filter out hover events.