如果将 MouseArea 放置在筛选 child 鼠标事件的 Item(例如 Flickable、SwipeView )中,则当父 Item 识别出手势(例如滑动)时,鼠标事件可能会从 MouseArea 中被过滤。如果将 preventStealing 属性设置为 true,则任何 Item 都不会窃取该 MouseArea 的鼠标事件。(注意,一旦某 Item 开始窃取事件,将 preventStealing 设置为 true 后,直到下一次相关事件才生效)
这个属性是 MouseArea 的,那么对于我们自定义的 C++ QQuickItem 该如何处理呢?通过 Qt 源码,可以看到是调用 QQuickItem 的 setKeepMouseGrab 函数进行设置(配合 setAcceptedMouseButtons(Qt::LeftButton) 启用了鼠标事件才有效)。
相关 Qt 源码:
//MouseArea
bool QQuickMouseArea::preventStealing() const
{
Q_D(const QQuickMouseArea);
return d->preventStealing;
}
void QQuickMouseArea::setPreventStealing(bool prevent)
{
Q_D(QQuickMouseArea);
if (prevent != d->preventStealing) {
d->preventStealing = prevent;
setKeepMouseGrab(d->preventStealing && d->enabled);
emit preventStealingChanged();
}
}
//Flickable
bool QQuickFlickable::filterMouseEvent(QQuickItem *receiver, QMouseEvent *event)
{
Q_D(QQuickFlickable);
QPointF localPos = mapFromScene(event->windowPos());
Q_ASSERT_X(receiver != this, "", "Flickable received a filter event for itself");
if (receiver == this && d->stealMouse) {
// we are already the grabber and we do want the mouse event to ourselves.
return true;
}
bool receiverDisabled = receiver && !receiver->isEnabled();
bool stealThisEvent = d->stealMouse;
bool receiverKeepsGrab = receiver && (receiver->keepMouseGrab() || receiver->keepTouchGrab());
if ((stealThisEvent || contains(localPos)) && (!receiver || !receiverKeepsGrab || receiverDisabled)) {
QScopedPointer mouseEvent(QQuickWindowPrivate::cloneMouseEvent(event, &localPos));
mouseEvent->setAccepted(false);
switch (mouseEvent->type()) {
case QEvent::MouseMove:
d->handleMouseMoveEvent(mouseEvent.data());
break;
case QEvent::MouseButtonPress:
d->handleMousePressEvent(mouseEvent.data());
d->captureDelayedPress(receiver, event);
stealThisEvent = d->stealMouse; // Update stealThisEvent in case changed by function call above
break;
case QEvent::MouseButtonRelease:
d->handleMouseReleaseEvent(mouseEvent.data());
stealThisEvent = d->stealMouse;
break;
default:
break;
}
if ((receiver && stealThisEvent && !receiverKeepsGrab && receiver != this) || receiverDisabled) {
d->clearDelayedPress();
grabMouse();
} else if (d->delayedPressEvent) {
grabMouse();
}
const bool filtered = stealThisEvent || d->delayedPressEvent || receiverDisabled;
if (filtered) {
event->setAccepted(true);
}
return filtered;
} else if (d->lastPosTime != -1) {
d->lastPosTime = -1;
returnToBounds();
}
if (event->type() == QEvent::MouseButtonRelease || (receiverKeepsGrab && !receiverDisabled)) {
// mouse released, or another item has claimed the grab
d->lastPosTime = -1;
d->clearDelayedPress();
d->stealMouse = false;
d->pressed = false;
}
return false;
}
参考 Qt 文档:https://doc.qt.io/qt-5/qml-qtquick-mousearea.html
参考 Qt 源码:E:\Qt\qt-everywhere-src-5.15.0\qtdeclarative\src\quick\items\qquickmousearea_p.h