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

时间:2022-09-18 23:12:54

Context: I'm trying to create a fader-like widget that can have multiple instances in the same view, each of which can be controlled simultaneously by different fingers.

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

I want to use Qt's gesture recognition system, but I also need some functionality above and beyond the standard Qt::PanGesture. To this end, I've subclassed both QGesture and QGestureRecognizer. In FooGestureRecognizer::recognize(...), I'm currently intercepting both QMouseEvents and QTouchEvents (for the time being, at least).

我想使用Qt的手势识别系统,但我还需要一些超出标准Qt :: PanGesture的功能。为此,我将QGesture和QGestureRecognizer都分类。在FooGestureRecognizer :: recogn(...)中,我目前正在拦截QMouseEvents和QTouchEvents(暂时,至少)。

On Windows I only receive QMouseEvents - I handle them and everything works as expected (though obviously I don't have to deal with the multitouch problem when my input is from a physical mouse). The events I receive (in order):

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

  • QEvent::MouseButtonPress
  • A string of QEvent::MouseMoves
  • 一串QEvent :: MouseMoves

  • QEvent::MouseButtonRelease

On Android, I receive a strange mix of QMouseEvents and QTouchEvents (in order):

在Android上,我收到了QMouseEvents和QTouchEvents的奇怪组合(按顺序):

  • QEvent::TouchBegin
  • QEvent::MouseButtonPress
  • QEvent::MouseMove (with no actual change in position)
  • QEvent :: MouseMove(位置没有实际变化)

  • Another QEvent::MouseButtonPress (not sure why I needed another one)
  • 另一个QEvent :: MouseButtonPress(不知道为什么我需要另一个)

  • My actual string of QEvent::MouseMoves, as expected
  • 我的实际字符串QEvent :: MouseMoves,正如预期的那样

  • QEvent::MouseButtonRelease

The global attribute Qt::AA_SynthesizeMouseForUnhandledTouchEvents is true by default. Turning it off changes the events I receive to:

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

  • QEvent::TouchBegin

...nothing else.

Here's a precursor question then: What can I do inside QGestureRecognizer::recognize() to tell Qt that I'm handling the QEvent::TouchBegin, and that it doesn't need to synthesize a QEvent::MouseButtonPress for me? event->accept() doesn't appear to make any difference.

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

The actual question: If (as it appears) Qt is synthesizing MouseEvents from TouchEvents, why do I see I see QEvent::MouseMove and QEvent::MouseButtonRelease but not QEvent::TouchUpdate or QEvent::TouchRelease?

实际问题:如果(看起来)Qt正在从TouchEvents合成MouseEvents,为什么我看到我看到QEvent :: MouseMove和QEvent :: MouseButtonRelease但不是QEvent :: TouchUpdate或QEvent :: TouchRelease?

Code is available, but in the interests of conciseness I've not included it here. Please ask if needed.

代码是可用的,但为了简洁起见,我没有把它包含在这里。请询问是否需要。

1 个解决方案

#1


2  

From the QTouchEvent docs:

来自QTouchEvent文档:

The QEvent::TouchUpdate and QEvent::TouchEnd events are sent to the widget or item that accepted the QEvent::TouchBegin event. If the QEvent::TouchBegin event is not accepted and not filtered by an event filter, then no further touch events are sent until the next QEvent::TouchBegin.

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

The root of this problem is that QGestureRecognizer does not accept the initial TouchBegin, and hence we don't receive any further touch events. I got around this by:

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

  1. Creating a thin event filter QObject owned by my QGestureRecognizer.
  2. 创建由QGestureRecognizer拥有的精简事件过滤器QObject。

Containing the following code:

包含以下代码:

bool FooGestureRecognizer::FooEventFilter::eventFilter(QObject *Object, QEvent *Event)
{
  if(Event->type() == QEvent::TouchBegin)
  {
    return true;
  }
  else
  {
    return QObject::eventFilter(Object, Event);
  }
}
  1. Installing my event filter AND calling setAttribute(Qt::WA_AcceptTouchEvents) on every valid* Target that comes through FooGestureRecognizer::create().
  2. 安装我的事件过滤器并在通过FooGestureRecognizer :: create()发出的每个有效* Target上调用setAttribute(Qt :: WA_AcceptTouchEvents)。

Returning true from eventFilter tells Qt that my fader is interested in receiving further touch events, and these touch events are delivered as expected to the gesture recognizer.

从eventFilter返回true告诉Qt我的推子有兴趣接收进一步的触摸事件,并且这些触摸事件按预期传递给手势识别器。

This solution feels like a hack, and one that might not be necessary in future versions of Qt, so I'm going to keep an eye on this code.

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

Notes:

  • During the construction of a QGestureRecognizer, create() is called with a null Target (expecting a dummy QGesture to be returned). Watch out for this if you're installing event filters on all Targets.
  • 在构造QGestureRecognizer期间,使用null Target调用create()(期望返回虚拟QGesture)。如果您要在所有目标上安装事件过滤器,请注意这一点。

  • My application needs to handle desktop mouse events in one way, and multi-finger touch events in another, so I've disabled Qt::AA_SynthesizeMouseForUnhandledTouchEvents. Keeping this enabled may lead to other considerations (e.g. I'm not sure if you'd need to return true for all touch events in eventFilter, so as to avoid them being duplicated as synthesised mouse events).
  • 我的应用程序需要以一种方式处理桌面鼠标事件,而在另一种方式中处理多指触摸事件,因此我禁用了Qt :: AA_SynthesizeMouseForUnhandledTouchEvents。保持启用此功能可能会导致其他注意事项(例如,我不确定您是否需要为eventFilter中的所有触摸事件返回true,以避免它们被复制为合成鼠标事件)。

#1


2  

From the QTouchEvent docs:

来自QTouchEvent文档:

The QEvent::TouchUpdate and QEvent::TouchEnd events are sent to the widget or item that accepted the QEvent::TouchBegin event. If the QEvent::TouchBegin event is not accepted and not filtered by an event filter, then no further touch events are sent until the next QEvent::TouchBegin.

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

The root of this problem is that QGestureRecognizer does not accept the initial TouchBegin, and hence we don't receive any further touch events. I got around this by:

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

  1. Creating a thin event filter QObject owned by my QGestureRecognizer.
  2. 创建由QGestureRecognizer拥有的精简事件过滤器QObject。

Containing the following code:

包含以下代码:

bool FooGestureRecognizer::FooEventFilter::eventFilter(QObject *Object, QEvent *Event)
{
  if(Event->type() == QEvent::TouchBegin)
  {
    return true;
  }
  else
  {
    return QObject::eventFilter(Object, Event);
  }
}
  1. Installing my event filter AND calling setAttribute(Qt::WA_AcceptTouchEvents) on every valid* Target that comes through FooGestureRecognizer::create().
  2. 安装我的事件过滤器并在通过FooGestureRecognizer :: create()发出的每个有效* Target上调用setAttribute(Qt :: WA_AcceptTouchEvents)。

Returning true from eventFilter tells Qt that my fader is interested in receiving further touch events, and these touch events are delivered as expected to the gesture recognizer.

从eventFilter返回true告诉Qt我的推子有兴趣接收进一步的触摸事件,并且这些触摸事件按预期传递给手势识别器。

This solution feels like a hack, and one that might not be necessary in future versions of Qt, so I'm going to keep an eye on this code.

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

Notes:

  • During the construction of a QGestureRecognizer, create() is called with a null Target (expecting a dummy QGesture to be returned). Watch out for this if you're installing event filters on all Targets.
  • 在构造QGestureRecognizer期间,使用null Target调用create()(期望返回虚拟QGesture)。如果您要在所有目标上安装事件过滤器,请注意这一点。

  • My application needs to handle desktop mouse events in one way, and multi-finger touch events in another, so I've disabled Qt::AA_SynthesizeMouseForUnhandledTouchEvents. Keeping this enabled may lead to other considerations (e.g. I'm not sure if you'd need to return true for all touch events in eventFilter, so as to avoid them being duplicated as synthesised mouse events).
  • 我的应用程序需要以一种方式处理桌面鼠标事件,而在另一种方式中处理多指触摸事件,因此我禁用了Qt :: AA_SynthesizeMouseForUnhandledTouchEvents。保持启用此功能可能会导致其他注意事项(例如,我不确定您是否需要为eventFilter中的所有触摸事件返回true,以避免它们被复制为合成鼠标事件)。