How to emit a signal from a QPushButton when the mouse hovers over it?
Asked Answered
F

5

11

Recently, I wanted that QPushButton can emit a signal, when the mouse pointer enters. How can I make it?

I know that QPushButton has some already defined signal, such as clicked(), pressed(), destory() and so on. But no signal like hover(), enter(), ...

I looked some information about it: Someone said it can be done by css. I don't understand. Can you give me some advice ? Thank you!

Fernandefernandel answered 13/2, 2012 at 13:14 Comment(3)
If you can explain what you would like to do when the mouse is hovering, it may not be necessary to intercept such an event. If for example, you want to change the appearance of the button, you can do this with a style sheet.Relative
Thank you .. I want to do that: If there are two Components, Once the mouse pointer is hover upon one, the other one is unvisiable...Fernandefernandel
Ok, since you want to affect a button based on mouse interaction with another button, you will indeed need to intercept this event.Relative
E
12

You can use QWidget::enterEvent ( QEvent * event ) for this.

You override this event and send a custom defined signal when ever this event occurs.

First you have to enable mouse tracking for this widget (setMouseTracking(true) in the constructor for example).

Header file:

class my_button
{
    // ...

protected:
    virtual void enterEvent( QEvent* e );

public Q_SIGNALS:
    void hovered();

    // ...
};

Source file:

void my_button::enterEvent( QEvent* e )
{
    Q_EMIT hovered();

    // don't forget to forward the event
    QWidget::enterEvent( e );
}

Where you use your button:

connect( one_of_my_button, SIGNAL(hovered()), this, SLOT(do_something_when_button_hovered()) );
Ens answered 13/2, 2012 at 13:26 Comment(1)
firstly、 Thank you . I think it is a bit comlicated, Because i just use one such button, Are there a other way ?Fernandefernandel
F
14

Although @Exa has answered this question, I want to show another solution which does not need to subclass QPushButton and is flexible in use! ( That's what I need in my project)

Step 1/2 : Overriding eventFilter.

LoginWindow.h:

// LoginWindow is where you placed your QPushButton 
//(= most probably your application windows)

class LoginWindow: public QWidget
{
public:
      bool eventFilter(QObject *obj, QEvent *event);
..
};

LoginWindow.cpp:

bool LoginWindow::eventFilter(QObject *obj, QEvent *event)
{
    // This function repeatedly call for those QObjects
    // which have installed eventFilter (Step 2)

    if (obj == (QObject*)targetPushButton) {
        if (event->type() == QEvent::Enter)
        {
        // Whatever you want to do when mouse goes over targetPushButton
        }
        return true;
    }else {
        // pass the event on to the parent class
        return QWidget::eventFilter(obj, event);
    }
}

Step 2/2 : Installing eventFilter on target widgets.

LoginWindow::LoginWindow()
{
    ...
    targetPushButton->installEventFilter(this);
    ...
}
Fawcette answered 23/5, 2014 at 18:31 Comment(6)
This is a very good answer. But for some bizarre reason, when I apply this logic on a QToolButton (for showing some custom text popup on hovering over it), the button becomes invisible, although hovering over where it is supposed to be reveals the popup all right, and even the cursor becomes pointer as expected, given I set it like that for the button!Twelfthtide
Perfect! I didn't want to create a new class for each widget I wanted to detect hover events for!Argali
@Cupidvogel I think I found the cause. Instead of return true in the eventFilter function, use return QWidget::eventFilter(obj, event); and one also doesn't need the else condition. I did this and the disappearing button condition went away.Whitening
Yep, found it few days back.. :)Twelfthtide
@Whitening Thanks for that! If that isn't added, then the whole logic of the PushButton goes out the window!Marinna
Thanks @Whitening for the disappearing fixGeomorphology
E
12

You can use QWidget::enterEvent ( QEvent * event ) for this.

You override this event and send a custom defined signal when ever this event occurs.

First you have to enable mouse tracking for this widget (setMouseTracking(true) in the constructor for example).

Header file:

class my_button
{
    // ...

protected:
    virtual void enterEvent( QEvent* e );

public Q_SIGNALS:
    void hovered();

    // ...
};

Source file:

void my_button::enterEvent( QEvent* e )
{
    Q_EMIT hovered();

    // don't forget to forward the event
    QWidget::enterEvent( e );
}

Where you use your button:

connect( one_of_my_button, SIGNAL(hovered()), this, SLOT(do_something_when_button_hovered()) );
Ens answered 13/2, 2012 at 13:26 Comment(1)
firstly、 Thank you . I think it is a bit comlicated, Because i just use one such button, Are there a other way ?Fernandefernandel
B
3

Make sure to add ':' after the public keyword

public: Q_SIGNALS:
    void hovered();
Bosson answered 9/9, 2013 at 13:31 Comment(0)
K
1

If I remember correctly, you need to enable mouse tracking for the button (Qt documentation) and override QWidget::onEnter() and QWidget::onLeave().

You will need to create a custom button class inheriting from QPushButton. You can define signals for mouseEnter and mouseLeave in your custom class and emit them from the onEnter() and onLeave() methods that you need to override.

Karyotype answered 13/2, 2012 at 13:25 Comment(1)
Yes, you must implement the onEnter() and onLeave() function in you custom button class. See @Exa's answer for the code example. ps. please up vote if you find a answer usefulKaryotype
O
1

So QT deal with mouse hovering using the "event" enterEvent (https://doc.qt.io/qt-5/qevent.html look for "QEvent::Enter"). This isn't about the Signal/Slot functionality (https://doc.qt.io/qt-5/signalsandslots.html), this is about Events (https://doc.qt.io/qt-5/eventsandfilters.html) We find enterEvent as a protected method at QWidget class (https://doc.qt.io/qt-5/qwidget.html) which is a base class for QPushButton class (https://doc.qt.io/qt-5/qpushbutton.html).

So what you have to do: to create a new class derived from QPushButton and override the protected method "enterEvent" that QPushButton inherited from QWidget.

Creating the new class:
QT Creator - File - New File or Project...
File and Classes - C++
C++ Class
Choose...
Base class - Custom - QPushButton
Next
define a name for your new class like MyPushButton

In mypushbutton.h:

#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H

#include <QPushButton>

class MyPushButton: public QPushButton
{
    Q_OBJECT
public:
    using QPushButton::QPushButton;  //inherits the QPushButton constructors

signals:
    void myPushButtonMouseHover();

protected:
    void enterEvent(QEvent *event);
};

#endif // MYPUSHBUTTON_H

In mypushbutton.cpp:

#include "mypushbutton.h"
#include <QMessageBox>

void MyPushButton::enterEvent(QEvent *event)
{
    QMessageBox::warning(this, "Mouse hover", "Mouse hovered MyPushButton"); //popping a message box

    emit myPushButtonMouseHover();  //emitting signal 

    QPushButton::QWidget::enterEvent(event);  //calling the "natural" enterEvent

}
Olfe answered 19/11, 2020 at 23:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.