LateJ | 03 February, 2011 08:45
While implementing one QML application, I needed to have access to multitouch pointer events. QML has a MouseArea element for handling pointer input, but unfortunately it does not support multitouch events. So by default you are limited to single touch pointer events. GestureArea (from Qt.labs) can be used to handle multitouch gestures, but I needed just the raw coordinates of the current touch points.
Before going any further, I want to point out that there's also a new element called TouchArea that is coming to QML. It seems to provide pretty much the same functionality that I'm implementing here, so in the future this post will probably become quite irrelevant.
The Qt Quick application created by the application wizard in Qt Creator contains a QmlApplicationViewer class, which handles things like orientation lock etc. The QmlApplicationViewer is actually inherited from QDeclarativeView, so it's easy to extend its functionality. One could also modify the QmlApplicationViewer class itself, but this is not a good idea since new Qt Creator versions will probably have updated version of the class, and modifying it would make updating difficult.
To intercept multitouch events and deliver them to QML, I did the following:
| touchapplicationviewer.h | touchapplicationviewer.cpp |
|
#ifndef TOUCHAPPLICATIONVIEWER_H #define TOUCHAPPLICATIONVIEWER_H #include "qmlapplicationviewer.h" class MultiTouch; class TouchApplicationViewer : public QmlApplicationViewer { Q_OBJECT public: explicit TouchApplicationViewer(MultiTouch* touch, QWidget *parent = 0); bool viewportEvent(QEvent *event); signals: public slots: private: MultiTouch* m_touch; }; #endif // TOUCHAPPLICATIONVIEWER_H |
#include "touchapplicationviewer.h" #include "multitouch.h" #include <QMouseEvent> TouchApplicationViewer::TouchApplicationViewer(MultiTouch* touch, QWidget *parent) : QmlApplicationViewer(parent), m_touch(touch) { qmlRegisterType<TouchPoint>("Multitouch", 1, 0, "TouchPoint"); } bool TouchApplicationViewer::viewportEvent(QEvent *event) { if (!m_touch) { return QmlApplicationViewer::viewportEvent(event); } switch (event->type()) { case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: m_touch->update(*(static_cast<QTouchEvent *>(event))); return true; default: return QmlApplicationViewer::viewportEvent(event); } } |
For exposing the touch point list to QML, I implemented two classes, TouchPoint and MultiTouch. MultiTouch class exposes the list of touchpoints to QML as a QList<TouchPoint*>. The sources for these classes are included in the attached project.
The test application is very simple. It shows the number of touch points in the middle of the screen, and also draws colored circles in the touch point coordinates. Here's a screenshot of the application running on device with two fingers on the screen:
And here's the QML source code for the application:
import QtQuick 1.0
import Multitouch 1.0
Rectangle {
id: root
width: 360
height: 640
property variant touchPoints: multitouch.touchPoints
Repeater {
id: repeater
anchors.fill: parent
model: touchPoints.length
Rectangle {
color: index == 0 ? "blue" : "red"
x: touchPoints[index].x - width/2
y: touchPoints[index].y - height/2
width: 80
height: 80
radius: 40
}
}
Text {
id: textfield
text: "Touch points: "+touchPoints.length
anchors.centerIn: parent
}
}
Comments
Very helpful
adrz1 | 19/04/2012, 19:45
Thanks, i have implemented a two button control for a simple QML game using your idea.