问题
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).
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):
QEvent::MouseButtonPress
- A string of
QEvent::MouseMove
s QEvent::MouseButtonRelease
On Android, I receive a strange mix of QMouseEvent
s and QTouchEvent
s (in order):
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
The global attribute Qt::AA_SynthesizeMouseForUnhandledTouchEvents is true
by default. Turning it off changes the events I receive to:
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.
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
?
Code is available, but in the interests of conciseness I've not included it here. Please ask if needed.
回答1:
From the QTouchEvent docs:
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.
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:
- Creating a thin event filter
QObject
owned by myQGestureRecognizer
.
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()
.
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.
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.
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).
来源:https://stackoverflow.com/questions/23369431/why-does-my-qgesturerecognizer-not-receive-touch-events