用于处理触摸事件的对象,但也让它通过

时间:2016-02-10 10:12:10

标签: event-handling qml qt5 touch-event

我想创建一个像MultiPointTouchArea一样工作的对象(因此它会有touchUpdated信号)但它也不会窃取触摸,因此放在它下面的对象也会接收触摸事件。

解决方案可能需要创建C ++对象。

有没有一种简单的方法来创建这样的对象?是否可以在不“偷”它们的情况下处理(触摸)事件?任何暗示都将受到赞赏。

这是我想要做的一个例子。我想触摸顶部Rectangle,但同时我想要MultiPointTouchArea两个进程触摸:

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.")
            }
        }
    }
}

如果我找到工作解决方案,我会在这里发布。我现在将尝试实施Mitchsolution

1 个答案:

答案 0 :(得分:2)

您可以继承QQuickItem并覆盖touchEvent()函数:

  

可以在子类中重新实现此事件处理程序,以接收项目的触摸事件。事件信息由事件参数提供。

您可能需要明确将accepted设置为false,以确保该项目不会窃取这些事件:

  

设置accept参数表示事件接收者想要该事件。不需要的事件可能会传播到父窗口小部件。默认情况下,isAccepted()设置为true,但不要依赖于此,因为子类可能会选择在构造函数中清除它。

我可以验证上述操作会导致较低的触摸区域在播放后进行所有事件(在Android手机上测试)。在这种情况下,您需要以某种方式过滤事件。一种方法是在QQuickItem子类中声明一个属性,该属性将用于指向较低的触摸区域。当该属性更改时,请在触摸区域上安装事件过滤器:

<强> 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
        }
    }
}

您可以详细了解事件过滤器here