为什么我的QGestureRecognizer没有收到触摸事件?

时间:2014-04-29 15:48:51

标签: android c++ qt qt5 qt5.2

上下文:我试图创建一个类似推子的小部件,可以在同一视图中有多个实例,每个实例都可以由不同的手指同时控制。

我想使用Qt' gesture recognition system,但我还需要一些超出标准Qt::PanGesture的功能。为此,我将QGestureQGestureRecognizer分为两类。在FooGestureRecognizer::recognize(...)中,我目前正在拦截QMouseEventQTouchEvent(至少目前为止)。

在Windows上我只收到QMouseEvent - 我处理它们,一切都按预期工作(虽然当我的输入来自物理鼠标时,显然我不必处理多点触控问题)。我收到的事件(按顺序):

  • QEvent::MouseButtonPress
  • 一串QEvent::MouseMove s
  • QEvent::MouseButtonRelease

在Android上,我收到了QMouseEventQTouchEvent s的奇怪组合(按顺序):

  • QEvent::TouchBegin
  • QEvent::MouseButtonPress
  • QEvent::MouseMove(位置没有实际变化)
  • 另一个QEvent::MouseButtonPress(不知道为什么我需要另一个)
  • 我的QEvent::MouseMove s的实际字符串,正如预期的那样
  • QEvent::MouseButtonRelease

默认情况下,全局属性Qt::AA_SynthesizeMouseForUnhandledTouchEventstrue。关闭它会将我收到的事件更改为:

  • QEvent::TouchBegin

......别的。

这里有一个前兆问题:我可以在QGestureRecognizer::recognize()内做什么告诉Qt我处理QEvent::TouchBegin,并且它没有需要为我合成QEvent::MouseButtonPress吗? event->accept()似乎没有任何区别。

实际问题:如果(如图所示)Qt正在从MouseEvent s合成TouchEvent s,为什么我会看到QEvent::MouseMoveQEvent::MouseButtonRelease但不是QEvent::TouchUpdateQEvent::TouchRelease

代码可用,但为了简明起见,我没有在此处包含它。如果需要请询问。

1 个答案:

答案 0 :(得分:2)

来自QTouchEvent docs

  

QEvent :: TouchUpdate和QEvent :: TouchEnd事件被发送到接受QEvent :: TouchBegin事件的小部件或项目。如果QEvent :: TouchBegin事件未被接受且未被事件过滤器过滤,则在下一个QEvent :: TouchBegin之前不会再发送任何触摸事件。

此问题的根源是QGestureRecognizer不接受初始TouchBegin,因此我们不会再收到任何触摸事件。我绕过这个:

  1. 创建由QObject拥有的精简事件过滤器QGestureRecognizer
  2. 包含以下代码:

    bool FooGestureRecognizer::FooEventFilter::eventFilter(QObject *Object, QEvent *Event)
    {
      if(Event->type() == QEvent::TouchBegin)
      {
        return true;
      }
      else
      {
        return QObject::eventFilter(Object, Event);
      }
    }
    
    1. 安装我的事件过滤器并在setAttribute(Qt::WA_AcceptTouchEvents)出现的每个有效* Target上调用FooGestureRecognizer::create()
    2. true返回eventFilter告诉Qt我的推子有兴趣接收更多触摸事件,并且这些触摸事件会按预期传递给手势识别器。

      这个解决方案感觉像是一个黑客,而且在未来的Qt版本中可能没有必要,所以我将密切关注这段代码。

      注意:

      • 在构建QGestureRecognizer期间,调用create()并使用空Target(期望返回虚拟QGesture)。如果您要在所有Target上安装事件过滤器,请注意这一点。
      • 我的应用程序需要以一种方式处理桌面鼠标事件,而在另一种方式中处理多指触摸事件,因此我已禁用Qt::AA_SynthesizeMouseForUnhandledTouchEvents。保持启用此功能可能会导致其他注意事项(例如,我不确定return true中的所有触摸事件是否需要eventFilter,以避免它们被复制为合成鼠标事件。