c++ - 如何拦截Qt Quick qml事件?

标签 c++ qt qml qtquick2 qtquickcontrols2

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

最佳答案

这可以通过安装 event filter 来实现在顶层窗口中。 通过保存对 ApplicationWindow 的引用,可以在 QML 源代码的任何地方找到和访问顶层窗口。使用 QML Singleton(这并不完全是微不足道的:遵循 this 或其他指南并将引用保存在 ApplicationWindowComponent.onCompleted 事件中)。可以使用 C++ QML 注册插件安装事件过滤器。

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

#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;
};

它必须像这样在 Qt Quick 应用程序之前注册:

    qmlRegisterType<QmlEventFilter>("MyPlugins", 1, 0, "EventFilter");

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

import MyPlugins 1.0

[...]

EventFilter
{
    id: filter
    filterEnabled: true // It can also be enabled on demand in other events
    Keys.onPressed:
    {
        // Accepting the event won't propagate the event
        // with the default event chain
        event.accepted = true
        console.log("onPressed")
    }
}

Component.onCompleted:
{
    // Singleton.window is the top level QML ApplicationWindow
    filter.source = Singleton.window
}

关于c++ - 如何拦截Qt Quick qml事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44605241/

相关文章:

c++ - 使用winsock的多线程国际象棋

c++ - QFileDialog (QT 5.2.1/mingw32) 不允许我选择只读文件

c++ - Qt 5.12 Mac OS X 版本号bug

c++ - Qt 中的自定义事件

c++ - 非虚拟多重继承示例

C++ 输出对齐和小数点占位符?

c++ - 使用库依赖项的相对路径,

c++ - 如何注册 Qt C++ 对象以在 QML 中使用它

javascript - Loader组件只加载一次

qt - MouseArea 覆盖 QML 行(或自动调整图像+文本大小)