如何拦截Qt Quick qml事件?

时间:2017-06-17 13:33:48

标签: c++ qt qml qtquick2 qtquickcontrols2

我想拦截Qt Quick事件,例如key events,以便我可以在它们到达当前目标(例如当前focused item之前)处理它们,可选地阻止事件在默认事件链。这可以通过在QML代码中处理事件来实现吗?

1 个答案:

答案 0 :(得分:2)

这可以通过在顶级窗口中安装event filter来实现。 通过使用QML Singleton保存对ApplicationWindow的引用,可以在QML源中的任何位置找到并访问顶级窗口(这不是非常简单:按照this或其他指南并保存引用Component.onCompleted的{​​{1}}事件。可以使用C ++ QML注册插件安装事件过滤器。

c ++事件过滤器插件是这样的:

ApplicationWindow

必须在Qt Quick应用程序之前注册,如下所示:

#pragma once

#include <QQuickItem>

class QmlEventFilter : public QQuickItem
{
    Q_OBJECT
public:
    Q_PROPERTY(QObject * source READ getSource WRITE setSource)
    Q_PROPERTY(bool filterEnabled READ getFilterEnabled WRITE setFilterEnabled)

public:
    QmlEventFilter()
    {
        m_source = nullptr;
        m_filterEnabled = false;
    }

    ~QmlEventFilter()
    {
        if (m_source != nullptr)
            m_source->removeEventFilter(this);
    }

    void setSource(QObject *source)
    {
        source->installEventFilter(this);
        m_source = source;
    };

    QObject * getSource() { return m_source; }
    void setFilterEnabled(bool value) { m_filterEnabled = value; }
    bool getFilterEnabled() { return m_filterEnabled; }

private:

    void keyPressEvent(QKeyEvent *event) override
    {
        // This is actually called when the QML event handler hasn't accepted the event
        m_qmlAccepted = false;

        // Ensure the event won't be propagated further
        event->setAccepted(true);
    }

    void keyReleaseEvent(QKeyEvent *event) override
    {
        // This is actually called when the QML event handler hasn't accepted the event
        m_qmlAccepted = false;

        // Ensure the event won't be propagated further
        event->setAccepted(true);
    }

    bool eventFilter(QObject *obj, QEvent *event) override
    {
        if (!m_filterEnabled)
            return false;

        bool ret = false;
        switch (event->type())
        {
        case QEvent::KeyPress:
        case QEvent::KeyRelease:
            m_qmlAccepted = true;
            QCoreApplication::sendEvent(this, event);
            ret = m_qmlAccepted;
            break;
        }
        return ret;
    }

private:
    QObject *m_source;
    bool m_filterEnabled;
    bool m_qmlAccepted;
};

然后它可以在像这样的QML源中使用:

    qmlRegisterType<QmlEventFilter>("MyPlugins", 1, 0, "EventFilter");
相关问题