如果將 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<QMouseEvent> 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