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 QMouseEvent
s and QTouchEvent
s (for the time being, at least).
我想使用Qt的手势识别系统,但我还需要一些超出标准Qt :: PanGesture的功能。为此,我将QGesture和QGestureRecognizer都分类。在FooGestureRecognizer :: recogn(...)中,我目前正在拦截QMouseEvents和QTouchEvents(暂时,至少)。
On Windows I only receive QMouseEvent
s - 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::MouseMove
s QEvent::MouseButtonRelease
一串QEvent :: MouseMoves
On Android, I receive a strange mix of QMouseEvent
s and QTouchEvent
s (in order):
在Android上,我收到了QMouseEvents和QTouchEvents的奇怪组合(按顺序):
QEvent::TouchBegin
QEvent::MouseButtonPress
-
QEvent::MouseMove
(with no actual change in position) - Another
QEvent::MouseButtonPress
(not sure why I needed another one) - My actual string of
QEvent::MouseMove
s, as expected QEvent::MouseButtonRelease
QEvent :: MouseMove(位置没有实际变化)
另一个QEvent :: MouseButtonPress(不知道为什么我需要另一个)
我的实际字符串QEvent :: MouseMoves,正如预期的那样
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 MouseEvent
s from TouchEvent
s, 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,因此我们不会再收到任何触摸事件。我绕过这个:
- Creating a thin event filter
QObject
owned by myQGestureRecognizer
.
创建由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);
}
}
- Installing my event filter AND calling
setAttribute(Qt::WA_AcceptTouchEvents)
on every valid*Target
that comes throughFooGestureRecognizer::create()
.
安装我的事件过滤器并在通过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 nullTarget
(expecting a dummyQGesture
to be returned). Watch out for this if you're installing event filters on allTarget
s. - 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 toreturn true
for all touch events ineventFilter
, so as to avoid them being duplicated as synthesised mouse events).
在构造QGestureRecognizer期间,使用null Target调用create()(期望返回虚拟QGesture)。如果您要在所有目标上安装事件过滤器,请注意这一点。
我的应用程序需要以一种方式处理桌面鼠标事件,而在另一种方式中处理多指触摸事件,因此我禁用了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,因此我们不会再收到任何触摸事件。我绕过这个:
- Creating a thin event filter
QObject
owned by myQGestureRecognizer
.
创建由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);
}
}
- Installing my event filter AND calling
setAttribute(Qt::WA_AcceptTouchEvents)
on every valid*Target
that comes throughFooGestureRecognizer::create()
.
安装我的事件过滤器并在通过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 nullTarget
(expecting a dummyQGesture
to be returned). Watch out for this if you're installing event filters on allTarget
s. - 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 toreturn true
for all touch events ineventFilter
, so as to avoid them being duplicated as synthesised mouse events).
在构造QGestureRecognizer期间,使用null Target调用create()(期望返回虚拟QGesture)。如果您要在所有目标上安装事件过滤器,请注意这一点。
我的应用程序需要以一种方式处理桌面鼠标事件,而在另一种方式中处理多指触摸事件,因此我禁用了Qt :: AA_SynthesizeMouseForUnhandledTouchEvents。保持启用此功能可能会导致其他注意事项(例如,我不确定您是否需要为eventFilter中的所有触摸事件返回true,以避免它们被复制为合成鼠标事件)。