I want to create an object that will work like MultiPointTouchArea
(so it will have touchUpdated signal) but also it would not steal touches, so that objects placed beneath it will receive the touch events as well.
The solution may require creating C++ object.
Is there a simple way to create such object? Is it possible to process (touch) events without "stealing" them? Any hint will be appreciated.
Here is an example of what I am trying to do. I want to touch top Rectangle
but at the same time I want both MultiPointTouchArea
s process touches:
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
visible: true
width: 300
height: 300
Rectangle {
id: rectangle1
anchors.centerIn: parent
width: 150
height: width
color: "red"
MultiPointTouchArea {
anchors.fill: parent
mouseEnabled: false
onTouchUpdated: {
console.log("Bottom touch area contains:",
touchPoints.length,
"touches.")
}
}
}
Rectangle {
id: rectangle2
anchors.centerIn: parent
width: 100
height: width
color: "blue"
MultiPointTouchArea {
anchors.fill: parent
mouseEnabled: false
onTouchUpdated: {
console.log("Top touch area contains:",
touchPoints.length,
"touches.")
}
}
}
}
If I will find working solution I will post it here. I will be trying now to implement Mitch's solution.
You can subclass QQuickItem
and override the touchEvent()
function:
This event handler can be reimplemented in a subclass to receive touch events for an item. The event information is provided by the event parameter.
You'll probably need to explicitly set accepted
to false
to ensure that the item doesn't steal the events:
Setting the accept parameter indicates that the event receiver wants the event. Unwanted events might be propagated to the parent widget. By default, isAccepted() is set to true, but don't rely on this as subclasses may choose to clear it in their constructor.
I can verify that the above will result in the lower touch area taking all events after the press (tested on an Android phone). In that case, you'll need to filter the events somehow. One way to do this is, inside your QQuickItem subclass, declare a property that will be used to point to the lower touch area. When that property changes, install an event filter on the touch area:
main.cpp:
#include <QGuiApplication>
#include <QtQuick>
class CustomTouchArea : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(QQuickItem *targetTouchArea READ targetTouchArea WRITE setTargetTouchArea NOTIFY targetTouchAreaChanged)
public:
CustomTouchArea() :
mTargetTouchArea(0) {
}
bool eventFilter(QObject *, QEvent *event) {
if (event->type() == QEvent::TouchUpdate) {
qDebug() << "processing TouchUpdate...";
}
// other Touch events here...
return false;
}
QQuickItem *targetTouchArea() const {
return mTargetTouchArea;
}
void setTargetTouchArea(QQuickItem *targetTouchArea) {
if (targetTouchArea == mTargetTouchArea)
return;
if (mTargetTouchArea)
mTargetTouchArea->removeEventFilter(this);
mTargetTouchArea = targetTouchArea;
if (mTargetTouchArea)
mTargetTouchArea->installEventFilter(this);
emit targetTouchAreaChanged();
}
signals:
void targetTouchAreaChanged();
private:
QQuickItem *mTargetTouchArea;
};
int main(int argc, char *argv[])
{
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<CustomTouchArea>("App", 1, 0, "CustomTouchArea");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
#include "main.moc"
main.qml:
import QtQuick 2.3
import QtQuick.Window 2.2
import App 1.0
Window {
visible: true
width: 300
height: 300
Rectangle {
id: rectangle1
anchors.centerIn: parent
width: 150
height: width
color: "red"
MultiPointTouchArea {
id: touchArea
anchors.fill: parent
mouseEnabled: false
onTouchUpdated: {
console.log("Bottom touch area contains:",
touchPoints.length,
"touches.")
}
}
}
Rectangle {
id: rectangle2
anchors.centerIn: parent
width: 100
height: width
color: "blue"
CustomTouchArea {
targetTouchArea: touchArea
anchors.fill: parent
}
}
}
You can read more about event filters here.