Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Why single mouse movement cause multiple event occurred



  • Here is a simple project for windows that trying to implement the simple dragging animation.
    But when it run, the widget won't be dragged by the mouse. It looks like it translate the position to the cursor for a short time but translate back to its original position.
    Look into the debug.txt, the event was sent multiple time about every move of the cursor, one occurred before the widget was moved and one after that moving. The first event's position info is about the old position of the widget but the second event's position info is about the new position of the widget. So the result is the widget was moved back to its original position by the second event process.
    Although I got a solution about this "multiple event occurred" is using global position information of the event, i.e. ,

    ev->x()
    ev->y()
    ev->pos()
    // change those to
    ev->globalX()
    ev->globalY()
    ev->globalPos()
    

    I was wander why a single mouse movement will cause multiple event to occurred.
    Hope I can get an answer about this question.

    #include "customwidget.h"
    #include <QApplication>
    #include <QMainWindow>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        // generate simple main window.
        QMainWindow w;
    
        // set the size of the window.
        w.setGeometry(0, 0, 800, 800);
    
        // generate the CustomWidget
        CustomWidget *widget = new CustomWidget(&w);
    
        // display the window containing the widget
        w.show();
    
        return a.exec();
    }
    
    

    main.cpp

    #ifndef CUSTOMWIDGET_H
    #define CUSTOMWIDGET_H
    
    #include <QWidget>
    #include <fstream>
    
    class CustomWidget : public QWidget
    {
        Q_OBJECT
    public:
        explicit CustomWidget(QWidget *parent = nullptr);
        ~CustomWidget();
    
    protected:
        // define the painting agorithm to see the area of this widget
        void paintEvent(QPaintEvent* ev);
    
        // handle the pressing event to initialize the dragging algorithm
        // and to track the start of moving event
        void mousePressEvent(QMouseEvent* ev);
    
        // implement the dragging algorithm
        void mouseMoveEvent(QMouseEvent* ev);
    
        // handle the releasing event to track the end of moving event
        void mouseReleaseEvent(QMouseEvent* ev);
    
    private:
        std::ofstream fout; // open file "debug.txt"
        QPoint prev; // to save the previous point of cursor.
    };
    
    #endif // CUSTOMWIDGET_H
    
    

    customwidget.cpp

    #include "customwidget.h"
    #include <QMouseEvent>
    #include <QPaintEvent>
    #include <QPainter>
    #include <QBrush>
    
    CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
    {
        // open file for output
        fout.open("debug.txt");
    
        // set the widget size and position
        setGeometry(0, 0, 100, 100);
    }
    
    CustomWidget::~CustomWidget()
    {
        // close file when program ended
        fout.close();
    }
    
    void CustomWidget::paintEvent(QPaintEvent *ev)
    {
        // draw the area with blue color
        QPainter painter(this);
        QBrush brush(Qt::GlobalColor::blue);
        painter.setBrush(brush);
        painter.setBackground(brush);
        painter.drawRect(ev->rect());
    }
    
    void CustomWidget::mousePressEvent(QMouseEvent *ev)
    {
        ev->accept();
    
        // debug output
        fout << "pressed at (" << ev->x() << ',' << ev->y() << ") current mouse ("
             << ev->globalX() << ',' << ev->globalY() << ')' << std::endl;
    
        // initialize the dragging start point
        prev = ev->pos();
    }
    
    void CustomWidget::mouseMoveEvent(QMouseEvent *ev)
    {
        ev->accept();
    
        // get the cursor position of this event
        const QPoint& pos = ev->pos();
    
        // debug output
        fout << "moved from (" << prev.x() << ',' << prev.y() << ") to ("
             << pos.x() << ',' << pos.y() << ") current mouse ("
             << ev->globalX() << ',' << ev->globalY() << ')' << std::endl;
    
        // calculate the cursor movement
        int dx = pos.x() - prev.x();
        int dy = pos.y() - prev.y();
    
        // move the widget position to match the direction of the cursor.
        move(geometry().x() + dx, geometry().y() + dy);
    
        // update the cursor position for the next event
        prev = pos;
    }
    
    void CustomWidget::mouseReleaseEvent(QMouseEvent *ev)
    {
        ev->accept();
        fout << "released at (" << ev->x() << ',' << ev->y() << ") current mouse ("
             << ev->globalX() << ',' << ev->globalY() << ')' << std::endl;
    }
    
    

    customwidget.h

    pressed at (61,61) current mouse (69,92)
    moved from (61,61) to (61,61) current mouse (69,92)
    moved from (61,61) to (61,59) current mouse (69,90)
    moved from (61,59) to (61,61) current mouse (69,90)
    released at (61,59) current mouse (69,90)
    
    

    debug.txt


    Edited:
    Include the current mouse global position output inside debug.txt.
    As you can see the same position sent two event to the widget.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    What OS are you on ?

    You might want to use a minimal distance before considering that the movement is valid. See the drag and drop examples.

    The mouse sensitivity can partly explain why you see several events.



  • I'm using Windows 10.
    Its hard to believe the event manager didn't do that for me, but I did some test without using mouse to move the cursor the result is only receive only one movement event.
    So you are right, I have to do the movement validate process before processing the event.
    Thanks for the help!



  • But this comes up with a new question for me:
    If event manager can detect the movement of the mouse even if that movement for system is like no movement, then can I get the exact movement with better precision?


  • Lifetime Qt Champion

    Do you mean native events ?



  • @SGaist Yeah, is there anyway to get those event detail?


  • Lifetime Qt Champion

    QAbstractNativeEventFilter might be of interest.



  • @SGaist I will take a look about that. Thanks for the info!


Log in to reply