Qurben
Qurben

Reputation: 1316

Event handlers in Qt

I am trying to implement a mouseover effect in Qt, but I don't know how to use the event handlers. I have created a simple Qt Widget Application with a pushButton. I am able to bind an event handler to the MainWindow like so:

MainWindow::enterEvent(QEvent *event)
{
    ui->pushButton_3->setGraphicsEffect(effect);
}

This works, the graphicsEffect is applied to the pushButton. But I don't understand how to bind the event handler to a single QObject. As far as I know is it not possible to use signals, because they only support click events and no mouseover events.

I am pretty new to Qt and I was not able to find any information I could understand.

Can anyone explain to me how to bind an event handler to a single QObject?

Thanks in advance.

Upvotes: 2

Views: 13283

Answers (3)

Qurben
Qurben

Reputation: 1316

I figured it out, in another way, by using the 'Promote to ...' option in the QtCreator. As also explained here: http://sector.ynet.sk/qt4-tutorial/customing-widgets.html

I added a class 'MyPushButton":

mypushbutton.h

#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H

#include <QPushButton>
#include <QGraphicsDropShadowEffect>

class MyPushButton : public QPushButton
{
    Q_OBJECT
public:
    MyPushButton(QWidget *parent = 0);

private:
    void enterEvent(QEvent *e);
    void leaveEvent(QEvent *e);

    QGraphicsDropShadowEffect *effect;
};

#endif // MYPUSHBUTTON_H

mypushbutton.cpp

#include "mypushbutton.h"

MyPushButton::MyPushButton(QWidget *parent)
    :QPushButton(parent)
{
    effect = new QGraphicsDropShadowEffect();
    effect->setBlurRadius(5);
    effect->setEnabled(false);
    this->setGraphicsEffect(effect);
}

void MyPushButton::enterEvent(QEvent *event)
{
    if (this->isEnabled())
        effect->setEnabled(true);
}

void MyPushButton::leaveEvent(QEvent *event)
{
    if (this->isEnabled())
        effect->setEnabled(false);
}

and then I right clicked my QPushButton in the editor and I selected 'Promote to ...' and I added MyPushButton as 'Promoted class name'.

It works like a charm and is very easy to expand or customize as it works with any event.

Upvotes: 6

cgmb
cgmb

Reputation: 4424

If you want to specify a behaviour dependant on events for QWidgets without subclassing every single one of them, it's possible to use event filters. Create an event filter, as described by Qt's documentation, and apply it the the widgets in question.

I wrote a simple example below, but note that using filters in this way becomes increasingly complex as you begin to have multiple interacting behaviours. I find they are most effective for simple behaviours that need to be applied across a number of different types of widgets.

class WidgetHoverEffectEnabler : public QObject
{
Q_OBJECT
public:
   WidgetHoverEffectEnabler(QObject* parent);

   virtual bool eventFilter(QObject* obj, QEvent* e);
};

WidgetHoverEffectEnabler::WidgetHoverEffectEnabler(QObject* parent)
: QObject(parent)
{
}

bool WidgetHoverEffectEnabler::eventFilter(QObject* obj, QEvent* e)
{
   if(QWidget* widget = qobject_cast<QWidget*>(obj))
   {
      QGraphicsEffect* effect = widget->graphicsEffect();
      if(effect)
      {
         if(e->type() == QEvent::Enter)
         {
            effect->setEnabled(true);
         }
         else if(e->type() == QEvent::Leave)
         {
            effect->setEnabled(false);
         }
      }
   }
   return QObject::eventFilter(obj, e);
}

Then you can install that filter on your widgets during their initialization:

// works on your button
QPushButton* button = new QPushButton;
QGraphicsDropShadowEffect* dropShadowEffect = new QGraphicsDropShadowEffect;
dropShadowEffect->setEnabled(false);
button->setGraphicsEffect(dropShadowEffect);
button->installEventFilter(new WidgetHoverEffectEnabler(button));

// works on any widget
QLabel* label = new QLabel("Read me!");
QGraphicsBlurEffect* blurEffect = new QGraphicsBlurEffect;
blurEffect->setEnabled(false);
label->setGraphicsEffect(blurEffect);
label->installEventFilter(new WidgetHoverEffectEnabler(label));

Upvotes: 1

Almo
Almo

Reputation: 15871

If you're working with a QPushButton, it's described pretty well here:

http://www.developer.nokia.com/Community/Wiki/How_to_use_QPushButton_in_Qt

For enter and leave events, look here: Finding current mouse position in QT

If, for example, you make something that inherits from QGraphicsRectItem, you can override the mouse event like this:

class BTNodeGraphicsItem : public QGraphicsRectItem
{
protected:
    virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
    // other class stuff
};

Then

void BTNodeGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
    // do stuff here
}

If you want the event to go further, then you add

QGraphicsRectItem::mousePressEvent(event);

in the handler routine.

Upvotes: 1

Related Questions