• QML与C++ 交互详解


    QML与C++ 交互详解

    这里我们分别介绍下QML 如何访问C++ 类,以及C++ 如何与QML 交互。

    (一) QML如何访问C++ 类:

    • 话不多说我们先看代码:
    #include "fpsitem.h"
    
    #include 
    #include 
    
    int main(int argc, char *argv[])
    {
    #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif
        QGuiApplication app(argc, argv);
    
        qmlRegisterType<FpsItem>("an.item", 1, 0, "FpsItem");
    
        QQmlApplicationEngine engine;
        const QUrl url(QStringLiteral("qrc:/main.qml"));
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                         &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
        engine.load(url);
    
        return app.exec();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    #ifndef FPSITEM_H
    #define FPSITEM_H
    
    #include 
    
    class FpsItem : public QQuickItem
    {
        Q_OBJECT
    
        Q_PROPERTY(int fps READ fps NOTIFY fpsChanged)
    
    public:
        FpsItem(QQuickItem *parent = nullptr);
    
        int fps() const;
    
    signals:
        void fpsChanged();
    
    private:
        int m_fps = 0;
        int m_frameCount = 0;
    };
    
    #endif // FPSITEM_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    #include "fpsitem.h"
    
    #include 
    #include 
    
    FpsItem::FpsItem(QQuickItem *parent)
        : QQuickItem(parent)
    {
        QTimer *timer = new QTimer(this);
        connect(timer, &QTimer::timeout, this, [this]{ m_fps = m_frameCount; m_frameCount = 0; emit fpsChanged(); });
        connect(this, &QQuickItem::windowChanged, this, [this]{
            if (window())
                connect(window(), &QQuickWindow::afterRendering, this
                        , [this]{ m_frameCount++; }, Qt::DirectConnection);
        });
        timer->start(1000);
    }
    
    int FpsItem::fps() const
    {
        return m_fps;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    import QtQuick 2.15
    import QtQuick.Window 2.15
    import QtQuick.Shapes 1.15
    
    import an.item 1.0
    
    Window {
        width: 640
        height: 480
        visible: true
        title: qsTr("FpsItem Test")
    
        FpsItem {
            id: fpsItem
        }
    
        Item {
            id: back
            anchors.fill: parent
            layer.enabled: true
            layer.smooth: true
            layer.samples: 8
    
            property bool running: false
    
            MouseArea {
                anchors.fill: parent
                onClicked: parent.running = !parent.running;
            }
    
            PathAnimation {
                target: ball
                running: back.running
                duration: 4000
                loops: -1
                path: Path {
                    startX: -ball.width * 0.5
                    startY: back.height - ball.height * 0.5
                    PathCurve { x: back.width * 0.8 - ball.width * 0.5; y: back.height * 0.8 - ball.height * 0.5 }
                    PathCurve { x: back.width * 0.2 - ball.width * 0.5; y: back.height * 0.2 - ball.height * 0.5 }
                    PathCurve { x: back.width - ball.width * 0.5; y: - ball.height * 0.5 }
                }
            }
    
            Shape {
                ShapePath {
                    strokeColor: "#ff1493"
                    fillColor: "transparent"
                    startX: 0
                    startY: back.height
                    PathCurve { x: back.width * 0.8; y: back.height * 0.8 }
                    PathCurve { x: back.width * 0.2; y: back.height * 0.2 }
                    PathCurve { x: back.width; y: 0 }
                }
            }
    
            Rectangle {
                id: ball
                x: -width * 0.5
                y: back.height - height * 0.5
                width: 50
                height: width
                radius: width * 0.5
                gradient: Gradient {
                    GradientStop { position: 0.20; color: "#af2020" }
                    GradientStop { position: 1.00; color: "#c27131" }
                }
                transformOrigin: Item.Center
                transform: Rotation {
                    axis { x: 1; y: 1; z: 0 }
    
                    NumberAnimation on angle {
                        running: back.running
                        duration: 1000
                        loops: -1
                        from: 0
                        to: 360
                    }
                }
            }
    
            Text {
                anchors.left: parent.left
                anchors.top: parent.top
                anchors.margins: 10
                font.pointSize: 12
                text: "FPS: " + fpsItem.fps
                color: "red"
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92

    首先我们来看下main.cpp

    1. qmlRegisterType方法: ,将会注册一个模块 an.item;组件的名字为:FpsItem
    2. QQmlApplicationEngine: 定义一个qml引擎;加载qml 文件
      再来看看qml文件:
    3. import an.item 1.0导入模块an.item
    4. FpsItem {
       id: fpsItem  }  使用组件,其中fpsItem中定义了一个属性fps可在qml中直接访问。
      
      • 1
      • 2
    5. 当然我们定义的FpsItem 是继承自QQuickItem的,无界面显示。如果想含有界面显示的可以继承QQuickWidget 或者是QQuickWindow 等。
    6. 这里对于Q_PROPERTY 这些QT 封装类的技巧就不在一一介绍,
    7. 感兴趣的同学可以去查阅下 Q_INVOKABLE 作为导出方法体供qml 直接使用。
    8. 关于C++ 如何与C++ 通信,下次再讲解。
  • 相关阅读:
    【JVM系列】- 启航·JVM概论学习
    verdi fsdb转vcd波形:用于后端功耗分析
    修改中文、英文参考文献在文末列表中的顺序:EndNote
    Web前端笔记1.0【Html详解,CSS详解】【Js待完善】
    什么是代理服务器
    OpenCV每日函数 计算摄影模块(5) 无缝克隆算法
    承装修试电力设施许可证怎么办理?承装修试电力设施许可证办理应该注意哪些?
    零基础直接上手java跨平台桌面程序,使用javafx(六)查询sqlite数据显示到TableView中
    升级:远程桌面软件玩游戏指南
    for、while、do While、for in、forEach、map、reduce、every、some、filter的使用
  • 原文地址:https://blog.csdn.net/weixin_42252757/article/details/126868588