如何在Qt中将点击事件传递给下面的兄弟?
Posted
技术标签:
【中文标题】如何在Qt中将点击事件传递给下面的兄弟?【英文标题】:How to pass click event to sibling underneath in Qt? 【发布时间】:2011-04-06 09:02:07 【问题描述】:我在窗口子 A 和子 B 中有两个重叠的小部件。子 A 在 B 上方并获取鼠标事件,但有时点击应该通过并最终击中子 B。
理想的解决方案是使用event->ignore()
,但这会将事件传递给父窗口小部件,而不是兄弟窗口。
“全部通过”解决方案setAttribute(Qt::WA_TransparentForMouseEvents);
也不起作用,因为子 A 需要捕获一些事件。
我如何告诉 Qt“我不想处理这个事件,就像我不在那里一样”?
【问题讨论】:
您能否设置“全部传递”选项并从鼠标事件处理程序重新发送鼠标事件?事件完成后,再次将其设置为 false。可能会导致无限递归.. 也许您应该在主窗口中为子 A 安装一个事件过滤器,尝试 A 是否管理事件,如果没有,检查它是否在子 B 的区域中,如果是,将其传递给它?这应该可行,但可能有点麻烦。否则,我会看到 A 应该知道 B 并能够将事件传递给它的可能性。 通过查看 Qt 的源代码,QWidgetPrivate::childAtRecursiveHelper
找到了一个匹配的孩子(过滤带有WA_TransparentForMouseEvents
的孩子,然后它调用孩子的事件处理程序,但是这个调用发生在孩子查找方法之外,所以唯一的解决方案似乎是从父级手动管理点击操作...
【参考方案1】:
更简单的解决方案(如果适用)是根据您的点击条件设置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 之后,所有这些都记在心里,所以请纠正我的名称或类型错误。
【讨论】:
我知道这是旧的,但你知道,一旦我激活它,我就无法将它设置为 false。 投了反对票,因为这是相当的 hack,并且可能通常适用于不会太快进入的点击事件,但如果应用程序挂起一小会儿并且多次点击进入,那么有些会可能触发错误。此处介绍的其他解决方案需要实施者进行更多工作,但更强大 imo。【参考方案2】:您也可以从另一面处理问题。您可以让其他小部件使用事件过滤器侦听第一个小部件的事件,而不是将事件转发到“其他”小部件。我不确定这是否适合您的用例,这取决于什么/谁确定什么事件将由哪个对象处理。
【讨论】:
【参考方案3】:如果事件必须被 Child-A 忽略,则发出一个信号并与其父级捕获它,然后父级发出一个新信号以由 Child-B 捕获
子 A -> 父 -> 子 B (信号)->(插槽)(信号)->(插槽)
【讨论】:
【参考方案4】:这是一个可能的选择:
-
将子 B 指针指向子 A 对象。
重新定义 bool QObjet::event(QEvent *event) 以在需要时将事件转发给子 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;
希望这会有所帮助。
【讨论】:
以上是关于如何在Qt中将点击事件传递给下面的兄弟?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 PyQt4 中将事件监听器添加到动态 QTableWidgetItem?