How to pass click event to sibling underneath in Qt?

邮差的信 提交于 2019-12-10 00:58:48

问题


I have two overlapping widgets in a window child A and child B. Child A is above B and gets mouse events but sometimes the click should pass through and eventually hit child B.

The ideal solution would have been to use event->ignore() but this passes the event to the parent widget, not siblings.

The "pass all" solution setAttribute(Qt::WA_TransparentForMouseEvents); does not work either because child A needs to capture some events.

How do I tell Qt "I do not want to handle this event, act like I am not there" ?


回答1:


The easier solution (if applicable) is to set WA_TransparentForMouseEvents depending on your click-through condition.

For example, if you want to click through certain regions of Child-A, you can use its mouseMoveEvent() to check whether WA_TransparentForMouseEvents needs to be set or unset. Then click events pass through automatically.

If you cannot determine whether a click event should be accepted before it has actually been triggered, you can do something like this:

void ChildA::mousePressEvent(QMouseEvent* event) {
    const bool accepted = ...; //insert custom logic here
    if (accepted) {
        ... //handle event here
    } else {
        //not accepting event -> resend a copy of this event...
        QMouseEvent* eventCopy = new QMouseEvent(*event);
        QApplication::instance()->postEvent(eventCopy);
        //...but this time, ignore it
        setAttribute(Qt::WA_TransparentForMouseEvents, true);
        QTimer::singleSlot(1, this, SLOT(resetClickTransparency()));
        //don't propagate original event any further
        event->accept();
    }
}

void ChildA::resetClickTransparency() { //slot
    setAttribute(Qt::WA_TransparentForMouseEvents, false);
}

Disclaimer: All of this written down by heart after a year of not doing Qt, so please correct me on name or type errors.




回答2:


You may also approach the issue from the other side. Instead of forwarding events to the "other" widget, you could have your other widget listen in to events for the first widget using an event filter. I am not sure if that fits your use case, it depends on what/who determines what events are to be handled by what object.




回答3:


If the event have to be ignored by Child-A, emit a signal and capture it with its parent, then the parent emits a new signal to be captured by Child-B

Child-A -> Parent -> Child-B
(Signal) -> (Slot)(Signal) -> (Slot)




回答4:


Here is a possible option :

  1. give the child B pointer to the child A objet.
  2. redefine bool QObjet::event(QEvent *event) to reforward the event to child B whenever needed.

For example :

bool WidgetA::event(QEvent *event)
 {
    QWidget::event( event);
    QEvent::Type type = event->type();
    if ( (type != QEvent::KeyPress) &&
         (type != QEvent::Wheel) &&
         (type != QEvent::MouseButtonDblClick) &&
         (type != QEvent::MouseMove) &&
         (type != QEvent::MouseButtonPress) )
        return true;
    //forward the event
    if ( m_pChildB )
         m_pChildB->event( event);
    return true;

 }

Hope this helps.



来源:https://stackoverflow.com/questions/5563862/how-to-pass-click-event-to-sibling-underneath-in-qt

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!