Как игнорировать QTapGesture после QTapAndHoldGesture - PullRequest
0 голосов
/ 22 мая 2018

Я хочу получить QTapAndHoldGesture и QTapGesture в моем виджете и выполнять разные действия в качестве реакции на эти жесты.Поэтому я переопределяю 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 завершено.

Мне нужен какой-то способ игнорировать это.Но я не вижу, как без повторной реализации платформы жестов: собирать положение и время события и фильтровать события на основе этой информации.Из-за того, что я получаю жесты один за другим и не могу соединиться QTapGesture и QTapAndHoldGesture.

Так можно ли игнорировать QTapGesture после QTapAndHoldGesture без сбора информации о положении и времени QGestureEvent

1 Ответ

0 голосов
/ 25 мая 2018

Поскольку для жеста QTapAndHoldGesture также требуется «Касание», ожидается, что он получит одновременно:

  • QTapAndHoldGesture, когда пользователь удерживает определенное время (конец таймера)
  • QTapGesture затем, когда пользователь отпускает касание

Поскольку они всегда будут приниматься в таком порядке, вы можете использовать этот факт, чтобы отфильтровать или отменить QTapGesture, который будет запущен, ноне завершено, когда вы получаете QTapAndHoldGesture, проверяется (то есть завершено).

Нет необходимости в информации о времени или позиции, если вы управляете одной точкой касания (Отказ от ответственности: следующее не проверено).

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 , поэтому может быть способ получить к нему доступ.

Существует также тип события GestureOverride, но я считаю, что в вашем случае этоне сработает.

...