Reputation: 1316
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
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
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
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