I want to get QTapAndHoldGesture
and QTapGesture
in my widget and do different thing as reaction on these gestures. So I override QWidget::event
method and add such code:
bool event(QEvent *event) override { if (event->type() == QEvent::Gesture) { auto g_event = static_cast<QGestureEvent *>(event); qDebug() << "GestureEvent BEGIN: gestures " << g_event->gestures().size() << ", active: " << g_event->activeGestures(); if (auto g = qobject_cast<QTapGesture *>(g_event->gesture(Qt::TapGesture))) { g_event->accept(g); return true; } if (auto g = qobject_cast<QTapAndHoldGesture *>(g_event->gesture(Qt::TapAndHoldGesture))) { if (g->state() == Qt::GestureFinished) { qDebug("FINISHED!!!"); g->setGestureCancelPolicy(QGesture::CancelAllInContext); } g_event->accept(g); return true; }
The problem is that I get not wanted QTapGesture
at the end of QTapAndHoldGesture
.
It looks like this:
GestureEvent BEGIN: gestures 1 , active: (QTapGesture(state=GestureStarted,hotSpot=773.396,492.884,position=773.396,492.884)) GestureEvent BEGIN: gestures 1 , active: (QTapGesture(state=GestureUpdated,hotSpot=773.396,492.884,position=773.396,492.884)) mouse event x 773 , y 493 GestureEvent BEGIN: gestures 1 , active: (QTapGesture(state=GestureUpdated,hotSpot=773.396,492.884,position=773.396,492.884)) ... GestureEvent BEGIN: gestures 1 , active: (QTapGesture(state=GestureUpdated,hotSpot=773.396,492.884,position=773.396,492.884)) GestureEvent BEGIN: gestures 1 , active: (QTapAndHoldGesture(state=GestureStarted,hotSpot=773,493,position=773,493,timeout=700)) GestureEvent BEGIN: gestures 1 , active: (QTapAndHoldGesture(state=GestureFinished,hotSpot=773,493,position=773,493,timeout=700)) FINISHED!!! GestureEvent BEGIN: gestures 1 , active: (QTapGesture(state=GestureUpdated,hotSpot=773.396,492.884,position=773.396,492.884)) GestureEvent BEGIN: gestures 1 , active: (QTapGesture(state=GestureUpdated,hotSpot=773.396,492.884,position=773.396,492.884)) GestureEvent BEGIN: gestures 1 , active: (QTapGesture(state=GestureFinished,hotSpot=773.396,492.884,position=773.396,492.884))
As you see at start I got QTapGesture
in started state, then QTapGesture
in updated state, after that QTapAndHoldGesture
and after that QTabGesture
finished.
I need some way to ignore it. But I don't see how without re-implementing of gesture framework: collect position and time of event and filter events based on this information. Because of I receive gestures one by one and can not connect QTapGesture
and QTapAndHoldGesture
.
So is it possible to ignore QTapGesture
after QTapAndHoldGesture
without collecting information about position and time of QGestureEvent
?
1 Answers
Answers 1
Because QTapAndHoldGesture
gesture also requires a "Tap", it is expected to receive both:
- QTapAndHoldGesture first, when the users holds for a certain time (end of a timer)
- QTapGesture then, when the user releases the touch
Because they will always be received in that order, you can use that fact, to filter or cancel the QTapGesture which will be started, but not finished, when you receive QTapAndHoldGesture is validated (i.e. finished).
No need for time or position information, if you are managing a single touch point (Disclamer: The following is untested).
bool MyClass::event(QEvent *event) override { // QPointer in case we receive partial events. Should remove "isNull()" keys at some point. static QMap<QPointer<QTapGesture*>, bool> tapGestures; if (event->type() != QEvent::Gesture) return QQuickItem::event(event); auto g_event = static_cast<QGestureEvent *>(event); if (auto g = qobject_cast<QTapGesture *>(g_event->gesture(Qt::TapGesture))) { // A TapAndHold was triggered during that tap... let's ignore it if (tapGestures.value(g)) g_event->ignore(g); // Or handle as you like if (g->state() == Qt::GestureFinished || g->state() == Qt::GestureCancelled) tapGestures.remove(g); else if (!tapGestures.contains(g)) tapGestures.insert(g, false); g_event->accept(g); return true; } if (auto g = qobject_cast<QTapAndHoldGesture *>(g_event->gesture(Qt::TapAndHoldGesture))) { // Probably not needed if the gesture handle doesn't conflict with another component //if (g->state() == Qt::GestureFinished) // g->setGestureCancelPolicy(QGesture::CancelAllInContext); // Mark all QTapGesture in progress to be ignored for (auto it = tapGestures.begin(); it != tapGestures.end(); ++it) it.value() = true; g_event->accept(g); return true; } }
All gestures are available in QGestureManager class, so there may be a way to access it.
There is also the GestureOverride event type, but I believe that in your case it will not be triggered.
0 comments:
Post a Comment