Search code examples
qteventsuser-interfacemouseeventkeyevent

Generating a QMouseEvent manually within the keyPressEvent in Qt


I have overridden the contentsMousePressEvent in my listview like this.

void AppListView::contentsMousePressEvent(QMouseEvent *e)
{
    AppGenericListView::contentsMousePressEvent(e);
    if (e->button() == Qt::RightButton)
        emit rightClicked();
    emit multiSelection();
}

Here is my keyPressEvent.

void AppListView::keyPressEvent(QKeyEvent * e)
{
    AppGenericListView::keyPressEvent(e);
    if ((e->key() == Qt::Key_Up) || (e->key() == Qt::Key_Down))
    {
        QListViewItem * item = currentItem();
        if (item)
        {
            const QRect rect = itemRect(item);
            QMouseEvent mEvt(QEvent::MouseButtonPress, rect.center(), Qt::LeftButton, Qt::LeftButton);
            contentsMousePressEvent(&mEvt);
        }
    }
}

For now, this code working fine. Please note that i'm not creating a dynamic QMouseEvent object. What i want to know is will this cause a crash in future ? Does contentMousePressEvent need a dyanamic object ? Qt doc doesn't say much about it. Any ideas ....


Solution

  • It won't crash, because you are not using event loop. But i think you should, for two reasons:

    1. You are simulating mouse press event but you are not serving it to the object as a such. For example, you don't serve your fake mouse event to mousePressEvent(). So for "natural" mouse press events and your simulated one, the application will behave differently. And you may forget why is that and you may get inexplicable crashes when your code evolves.

    2. The original system keypress event handling will be blocked by handling a mouse press event. You can't know who (what thread) will connect() to your signals emitted from overriden mouse event handler. Don't be surprised if you get a deadlock.

    Such a half baked shortcuts are good only as temporary solutions. In the long run, they will shoot at your back. If you really want a shortcut, stop pretending it's a mouse event and implement a special separate method which will be called also from the "real" mouse event. If you want a real mouse event, handled properly, create a dynamic QMouseEvent and enqueue it at the event loop.

    QMouseEvent* evt = new QMouseEvent(QEvent::MouseButtonPress,
      rect.center(),this->mapToGlobal(rect.center()),
     Qt::LeftButton, Qt::LeftButton);
    QCoreApplication::postEvent(this,evt);