如何将点击事件传递给Qt下的兄弟?

问题描述:

我在一个窗口子A和子B中有两个重叠的小部件。子A在B之上并且获取鼠标事件,但有时点击应该通过并最终碰到子B。如何将点击事件传递给Qt下的兄弟?

理想的解决方案是使用event->ignore()但这会将事件传递给父窗口小部件,而不是兄弟。

“全部通过”解决方案setAttribute(Qt::WA_TransparentForMouseEvents);不起作用,因为孩子A需要捕获一些事件。

我该如何告诉Qt“我不想处理这个事件,就像我不在那里一样?”?

+0

您可以设置“全部通过”选项并从鼠标事件处理程序重新发送鼠标事件吗?事件结束后,再次设置为false。可能导致无限递归..也许你应该在主窗口中为子A安装一个事件过滤器,试着如果A管理事件,如果不是,检查它是否在子B的区域,如果是,将它传递给它?这应该起作用,但可能有点破解。否则,我会看到A应该知道B并能够将事件传递给它的可能性。 – 0xbaadf00d 2011-04-06 09:16:09

+0

通过查看Qt的源代码,'QWidgetPrivate :: childAtRecursiveHelper'找到一个匹配的子项(用'WA_TransparentForMouseEvents'过滤这些子项,然后调用子项的事件处理程序,但是这个调用发生在子查找方法之外,所以唯一的解决方案似乎是管理点击从父母那里手工操作... – gaspard 2011-04-06 09:34:36

如果事件已经由儿童-A被忽略,发射的信号,并且与它的父捕获它,则该父发射至由儿童-B

儿童-A被捕获新的信号 - >父(信号) - >(插槽)

更容易的解决方案(如果适用)是根据您的点击条件设置WA_TransparentForMouseEvents

例如,如果要单击Child-A的某些区域,则可以使用它的mouseMoveEvent()来检查WA_TransparentForMouseEvents是否需要设置或取消设置。然后点击事件自动通过。

如果你不能确定一个点击事件是否应该被接受的话,其实是被触发之前,你可以做这样的事情:

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); 
} 

免责声明:一年所有这一切都通过心脏写下来后一不做Qt,所以请纠正我的名称或类型错误。

+0

我知道这是旧的,但只是你知道,一旦我激活它,我不能将它设置为假。 – Romain 2014-08-05 08:18:27

这里是一个可能的选择:

  1. 给小孩B指向孩子客体。
  2. 重新定义布尔QObjet :: event(QEvent *事件)以在需要时将事件重新转发给子B。

例如:

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; 

} 

希望这有助于。

您也可以从另一端处理问题。您可以让其他小部件使用事件过滤器监听第一个小部件的事件,而不是将事件转发到“其他”小部件。我不确定这是否适合您的用例,这取决于什么/谁决定哪些事件将由什么对象来处理。