16,212
社区成员
发帖
与我相关
我的任务
分享
QWidget *QApplication::widgetAt(const QPoint &p)
{
QWidget *window = QApplication::topLevelAt(p);
if (!window)
return 0;
QWidget *child = 0;
if (!window->testAttribute(Qt::WA_TransparentForMouseEvents))
child = window->childAt(window->mapFromGlobal(p));
if (child)
return child;
// ....
}
in QWidget.cpp:
QWidget *QWidget::childAt(const QPoint &p) const
{
return d_func()->childAt_helper(p, false);
}
QWidget *QWidgetPrivate::childAt_helper(const QPoint &p, bool ignoreChildrenInDestructor) const
{
if (children.isEmpty())
return 0;
// ...
return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
}
QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPoint &p, bool ignoreChildrenInDestructor, bool includeFrame) const
{
#ifndef Q_WS_MAC
Q_UNUSED(includeFrame);
#endif
for (int i = children.size() - 1; i >= 0; --i) {
QWidget *child = qobject_cast<QWidget *>(children.at(i));
if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents)
|| (ignoreChildrenInDestructor && child->data->in_destructor)) {
continue;
}
// ...
}
return 0;
}
2. QWidget::mousePressEvent()调的是event->ignore();QAbstractButton::mousePressEvent调用的是event->accept();。
3. 打印接收到鼠标事件的控件名,发现调用event->ignore()之后,消息被传递给了父控件,而调用event->accept();之后消息就不再传递了。
根据这3个条件,可以让绿色控件截获到鼠标事件后,“绕过”自己,向后面的控件发送消息:
void 绿色控件::mouseMoveEvent( QMouseEvent *e )
{
QWidget::mouseMoveEvent(e);
MyMouseEvent(e);
}
void 绿色控件::mousePressEvent( QMouseEvent *e )
{
QWidget::mousePressEvent(e);
MyMouseEvent(e);
}
void 绿色控件::mouseReleaseEvent( QMouseEvent *e )
{
QWidget::mouseReleaseEvent(e);
MyMouseEvent(e);
}
void 绿色控件::mouseDoubleClickEvent( QMouseEvent *e )
{
QWidget::mouseDoubleClickEvent(e);
MyMouseEvent(e);
}
void 绿色控件::MyMouseEvent( QMouseEvent *e )
{
if (this->parentWidget())
{
// 将自己设为鼠标事件透明并重新搜索是否有后面的控件会响应鼠标事件。
this->setAttribute(Qt::WA_TransparentForMouseEvents, true);
QPoint pt = this->mapTo(this->parentWidget(), e->pos());
QWidget *w = this->parentWidget()->childAt(pt);
if (w)
{
pt = w->mapFrom(this->parentWidget(), pt);
QMouseEvent *event = new QMouseEvent(e->type(), pt, e->button(), e->buttons(), e->modifiers());
QApplication::postEvent(w, event);
}
// 将自己设为鼠标事件不透明,以免影响button的功能
this->setAttribute(Qt::WA_TransparentForMouseEvents, false);
}
}