4
votes

I need to get mouse movement inside of a widget:

An eventFilter is not possible, since that would be installed on the QApplication. The widget is far down in the type hierarchy. Passing this widget up to the main function where the QApplication object is created would mess up the code.

Therefore I implemented

void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent * event);
void mouseMoveEvent(QMouseEvent *event);

in the widget.

None of the events is called. Even after setting mousetracking to true on both the central widget and the widget where I actually need the event, the functions are not called:

centralWidget->setMouseTracking(true);

How do you get mouse events in Qt for custom subclass of QWidget ?

Update: here is the .h file:

class Plot : public QWidget
{
    Q_OBJECT
//...

protected:
    void mousePressEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent * event);
    void mouseMoveEvent(QMouseEvent *event);

Update:

I tried the eventFilter approach.

in the .h file:

protected:
    void mousePressEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent * event);
    void mouseMoveEvent(QMouseEvent *event);

    bool eventFilter(QObject* object, QEvent* event);

in the .cpp :

void Plot::mousePressEvent(QMouseEvent *event){
//...
}
void Plot::mouseMoveEvent(QMouseEvent *event){

}
void Plot::mouseReleaseEvent(QMouseEvent *event){

}

bool Plot::eventFilter(QObject* object, QEvent* event)
{
    if(event->type() == QEvent::MouseButtonPress)
    {
        QMouseEvent* mev=static_cast<QMouseEvent*>(event);

        qDebug()<<mev->x();
    }
   return false;
}

Then in the constructor of my qWidget:

this->installEventFilter(this);

The code compiles and runs fine. Breakpoints at the if statement in the event filter stop the program, the eventFilter method is called. But the if statement is never evaluated to true. Even the simple buttonPress events are not registered.

The overwritten methods for the events are still not called.

2
Have you tried this ?Marco A.
Can you post the header file of your widget class?Gombat
you could use a normal event filter and check is it a mouse press, release or move event then cast it to a mouse event and then just do whatever you want with itAngryDuck
@AngryDuck, what is a normal event filter ?lhk
"An eventFilter is not possible, since that would be installed on the QApplication. " mmm, nope. An event filter can be installed on any QObject: doc.qt.io/qt-5/qobject.html#installEventFilter. There would be no need to move the object to the application's scope.Nicolas Holthaus

2 Answers

2
votes
bool someClass::eventFilter(QObject* object, QEvent* event)
{
    if(event->type() == QEvent::MouseMove)
    {
         mouseMoveFunction(static_cast<QMouseEvent*>(event))
    }
    // Repeat for other mouse events 

   // returning true blocks event returning false doesnt so if you want to block all mouse events except what your handling then return true inside each of your ifs
   return false;
}

then install the event filter on what ever you want the filter to be applied to ill assume for this that your in a ui class, which you would do like this (in the constructor)

this->installEventFilter(this)

EDIT: OP is using QCustomPlot, from previous experience i know this consumes all the events and doesnt pass them back up, so you have to connect to the mouse click (or whatever event you want) signal it emits with the point or event in it

1
votes

I too had need for filtering mouse events in a deep heiarchy, and this answer above didn't quite do it for me. I had to make a small tweek to get things to work.

You need to register the sub-classed widget with the QCoreApplication, but that can easily be done without traversing the hierarchy. In the sub-classed construtor put the following line:

QCoreApplication::instance()->installEventFilter(this);

Your sub-class will now receive all events and its just a matter of filtering what you need.

Full Example Below

Header File:
MouseMoveReaderBox : QScrollArea
{
    Q_OBJECT
public:
    explicit MouseMoveReaderBox(QWidget *parent = 0);
    ~MouseMoveReaderBox();

protected:
    bool eventFilter(QObject *obj, QEvent *event);
}

Source File:
#include "MouseMoveReaderBox"

MouseMoveReaderBox::MouseMoveReaderBox(QWidget *parent = 0):
    QScrollArea(parent)
{
     QCoreApplicaiton::instance()->installEventFilter(this);
}

bool MouseMoveReaderBox::eventFilter(QObject *obj, QEvent *event)
{
    if(event.type() == QEvent::MouseMove)
    {
        // logic here...
        return true;// if you want to intercept
    }
    // Other event type checks here...
    return false;//the signal will be delivered other filters
}

Hope this helps because I know I was pulling my hair out!