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

Changing QMouseEvent position



  • Hello,

    I feel this subject might be already solved, but I did'nt find it, sorry...
    I would like to change the position x-y of a QMouseEvent. (using Qt 5.11)
    For example, when clicking at x=120 & y=120, I would like the 100x100 QPushButton located at 0 to receive the press event.
    For the moment, I override event from a MainWindow class :

    bool MainWindow::event(QEvent *event)
    {
        if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseMove) 
        {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
            qDebug() << "Mouse event detected (" << event->type() << ")- x=" << mouseEvent->x() << " - y=" << mouseEvent->y() ;
    
            // I tried this but it does'nt change anything
            const QPoint newPos(mouseEvent->x() - 50, mouseEvent->y() - 50);
            mouseEvent->setLocalPos(newPos);
    
            return true;
        } 
        else 
        {
            // pass the event on to the parent class
            return QMainWindow::event(event);
        }
    }
    

    But this doesn't prevent the event to be located at (120,120)...

    I feel I am on the wrong direction.
    Any help would be greatly appreciated !
    Thank you !

    Etienne


  • Lifetime Qt Champion

    Hi
    Can you explain a bit what is the use case for this ?
    It sounds a bit strange so not sure i understand. :)

    So you have a windows MainWindow with a button on, and in case you click some where else on the MainWindow
    you want the button to get the MouseButtonPress anyway ?
    Regardless of where you click ?

    You could use
    http://doc.qt.io/qt-5/qwidget.html#grabMouse
    and all mouse events go to button until you release it but im not sure
    that is what you want.



  • Hi,

    I think you need to send a mouse press event yourself.
    But it seems there's more simple :

    [slot] void QAbstractButton::click()

    Performs a click.
    All the usual signals associated with a click are emitted as appropriate. If the button is checkable, the state of the button is toggled.



  • Thank you for you replies !

    The idea behind is a plan B in case I do not succeed in calibrating my touchscreen with my screen (sizes are different).
    So I need to catch all mouse's events in my app, perform a transformation for each (the calibration) and send new events with a different position. I although need catch events to be ignored by my app which should only received "calibrated events".
    My app contains different buttons and pages, so I would need something generic.

    @mpergand : When you say I think you need to send a mouse press event yourself, do you know how I can first make them ignored by all my QPushButton in my app ? That would be a nice first step ! After that, I may use this

    bool QCoreApplication::sendEvent(QObject * receiver, QEvent * event)
    

    to send my custom event

    Thank you for helping !


  • Lifetime Qt Champion

    @etiennedm
    Hi
    Ah, make more sense now.
    I really hope you can calibrate the screen.

    Anyway, i think overriding
    http://doc.qt.io/qt-5/qcoreapplication.html#notify
    would allow this - as this function will see any event before distributed.



  • @mrjj
    Thanks for pointing that out !
    I will look into this and try to make it work on a test example.


  • Moderators

    @etiennedm
    I think, you're on the right track for your situations.

    If you override the top most (mainWindow) Qwidget::event of your app you can calculate your offset position and detect transfer the event along via

    QWidget::childAt
    and
    QCoreApplication::sendEvent

    something along this

    bool MainWindow::event(QEvent *event)
    {
        if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseMove) 
        {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
    
            const QPoint newPos(mouseEvent->x() - 50, mouseEvent->y() - 50);
            QWidget *w = childAt(newPos);
    
            if(w)
               return QCoreApplication::sendEvent(qObject_cast<QObject *>(w), event);
           else
                return true;
        } 
    }
    


  • Thank you all ! Problem solved !

    I used a custom class inherited from QApplication to override notify as suggested by @mrjj
    I'm able to change the event before it is sent to the entire app, thanks !
    Code here :

    bool MyQApplication::notify(QObject *receiver, QEvent *event)
    {
        if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseMove)
        {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
            qDebug() << "Mouse event detected (" << event->type() << ")- x=" << mouseEvent->x() << " - y=" << mouseEvent->y();
    
            const QPoint newPos(mouseEvent->x() - 50, mouseEvent->y() - 50);
            mouseEvent->setLocalPos(newPos);
    
            return QApplication::notify(receiver, mouseEvent);
        }
        else
        {
            return QApplication::notify(receiver, event);
        }
    }
    

    Thanks,

    Etienne


  • Moderators

    @etiennedm
    great!

    But you'll have to modfy that code of yours a bit.
    I don't think that it would- currently - change to other objects, if your touch event is at the border of 2 objects and the offset would push the event to the next one.

    I might be wrong, or it might also depend on the z-order of the widgets, I'm unsure.



  • @J-Hilk Thank for helping me on this.
    Could you provide some details on what you're pointing out ?

    The test I ran seems to work well for me (maybe I mis-explained what I wanted to achieve), so when I click aside a button, I can "click" it adjusting the offset (overriding notify). When I click on it (native cursor on it), nothing happens. (as long as the offset is enough to go outside the button)

    I have some code running (largely based on this) if you want.

    Thanks !

    Etienne


  • Moderators

    @etiennedm
    I'm more thinking along the following line.

    you have 2 QPushButtons next to each other, seperated by (let's say) 10 px. The left one goes a page back and the right one a pge forwards ( in example a QStackedWidget).

    Now you have an offset of 50 in x direction.

    Now you press the touch screen, your calculation pushes the new postion to the forwards button, but physically QCoreApplication registered the back button as receiver object.

    As a result, your touchinput is ignored.


Log in to reply