如何在QTapAndHoldGesture之后忽略QTapGesture

问题描述 投票:9回答:1

我希望在我的小部件中获得QTapAndHoldGestureQTapGesture,并对这些手势做出不同的反应。所以我重写QWidget::event方法并添加这样的代码:

 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;
      }

问题是我在QTapGesture结束时不想要QTapAndHoldGesture

它看起来像这样:

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))

正如你在开始时看到的那样,QTapGesture处于启动状态,然后QTapGesture处于更新状态,之后QTapAndHoldGesture和之后的QTabGesture完成。

我需要一些方法来忽略它。但是我没有看到如果没有重新实现手势框架:收集事件的位置和时间并根据这些信息过滤事件。因为我一个接一个地接受手势,不能连接QTapGestureQTapAndHoldGesture

那么有可能在QTapGesture之后忽略QTapAndHoldGesture而没有收集关于QGestureEvent的位置和时间的信息吗?

c++ qt touch qt5 gesture
1个回答
6
投票

因为QTapAndHoldGesture手势也需要“Tap”,所以预计会同时收到:

  • QTapAndHoldGesture首先,当用户持有一段时间(计时器结束)
  • 然后QTapGesture,当用户释放触摸时

因为它们将始终以该顺序接收,所以当您收到QTapAndHoldGesture验证(即已完成)时,您可以使用该事实来过滤或取消将启动但未完成的QTapGesture。

如果您管理单个接触点,则无需时间或位置信息(免责声明:以下内容未经测试)。

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;
    }
}

所有手势都在QGestureManager class中提供,因此可能有办法访问它。

还有GestureOverride事件类型,但我相信在你的情况下它不会被触发。

© www.soinside.com 2019 - 2024. All rights reserved.