Qt – When I send or post a QMouseEvent, at the position of a QPushbutton, its clicked() signal is not emitted

buttonmouseeventqtsignalssignals-slots

I try to design a gui for an augmented reality application using the kinect. The idea is, to use the hands detected by the kinect skeleton tracking to control an application via gestures.

This question is not about gestures, as this part of my appilcation works fine.

In my application i want to simulate a mouse click whenever a click gesture is performed. To do this, i am sending two events one, mousebuttonpressed, and one mousebuttonreleased, as a normal click is also a series of press and release.

The whole thing works fine on a QWebView. In the browser window, i can "click" on links.

But for some reason i cannot "click" on a QPushButton. The clicked() signal is not emitted.
I have a short example to illustrate my problem:

First the main function:

int main(int argc, char **argv){
    QApplication app( argc, argv );
    QWebViewButtons mainapp( 0, Qt::Window );
    app.setActiveWindow( &mainapp );
    mainapp.show();
    mainapp.setApplication( &app ); //this is a setter to also get access to the main application in the widget
    return app.exec();
}

This is my own widget:

QWebViewButtons::QWebViewButtons(QWidget* parent, Qt::WindowFlags flags ): QWidget(parent, flags ){
    this->m_ui.setupUi( this );
    QObject::connect( this->m_ui.pushButton, SIGNAL(clicked(bool)), this, SLOT( buttonClicked(bool) ) );
}

void QWebViewButtons::mousePressEvent( QMouseEvent* event ){
    printf("mouse click, %d, %d\n", event->pos().x(), event->pos().y() );
}

void QWebViewButtons::buttonClicked( bool clicked ){
    printf("slot button clicked\n");    
}

void QWebViewButtons::keyPressEvent( QKeyEvent* event ){
    printf("Key pressed\n"); 
    QPoint pos( this->width()/2, this->height()/2 );
    QPoint global = this->mapToGlobal(pos);
    QWidget *w = this->m_app->widgetAt(global);
    //printf("widget under point of click: %s", w);
    QApplication::sendEvent( w, new QMouseEvent( QEvent::MouseButtonPress, pos, Qt::MouseButton::LeftButton, Qt::MouseButton::LeftButton, Qt::KeyboardModifier::NoModifier ) );
    QApplication::sendEvent( w, new QMouseEvent( QEvent::MouseButtonRelease, pos, Qt::MouseButton::LeftButton, Qt::MouseButton::LeftButton, Qt::KeyboardModifier::NoModifier ) );
}

I followed the suggestion here:
Qt Artificial mouse clicks doesnt work properly
and send to send my mouse events directly to the QPushButton. But that didn't help.
I also tried to send the mouse events to "this", or the main app.

Now I am running out of ideas.
What I want to have is, that the buttonClicked() slot is called if i press any key. But i only is called if i click the button with my mouse.
How can i accomplish this? Or is my basic idea completely false?

Thanks for your ideas.

Best Answer

So, do I get that right? When doing your "click-gesture" you come into keyPressEvent? If so, you can check whether the "click" has been done above the button and explicitly call the button's clicked() signal. But that's not what you want?

And what exactly is QWebViewButtons? The area the user does his gestures in?

Have you debugged into the keyPressEvent to see if your sendEvent has the correct widget (w)? I can't see why the widget should not recieve the event...

And remember that when new'ing a QMouseEvent and sending it via sendEvent is is never deleted. When using sendEvent you should create your event on the stack.

Maybe you should have a look at this thread, where a QTestEventList is recommended: Mimicking/faking a Mouse Click and Mouse Wheel using Qt. But I can imagine that you don't want test functions do the trick ;)

Related Topic