• Qt移动应用开发(六):QML与C++互动


    Qt移动应用开发(六):QML与C++互动

           上一篇文章讲到了在Qt Quick中实现场景切换的一种可能的方法,场景切换是诸如游戏等应用在内必需要面临的技术难点,所以场景切换并没有通行的方法,依据自己的使用习惯进行设计就可以。

           本文主要介绍的是怎样使用QML和C++进行交互,难度略微偏大,适合有经验的Qt开发人员进行学习交流。

           Qt 5吸收了Qt 4的declarative模块的长处,对底层进行了更改,新建了QPA层,隔离了不同操作系统API和上层Qt代码。同一时候QML/QtQuick也能够顺利在不同平台上执行。另外因为考虑到让Qt程序接入不同的库函数,因此Qt开放了接口让QML层和C++代码进行交互。

    之前已经有较多介绍QML与C++交互的文章了,本文仅作为一种故意的补充,很多其它相关的知识能够查询Qt帮助文档或向我留言。

           本文的样例在Qt 5.3.1中顺利编译执行通过。

    原创文章,反对未声明的引用。原博客地址:http://blog.csdn.net/gamesdev/article/details/37359873

           首先一个较为简单的方法就是注冊上下文属性(Context Property)。让QML訪问C++的变量。

    代码例如以下:

    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        engine.rootContext( )->setContextProperty(
                    "Greeting",
                    QObject::tr( "Hello QML from C++" ) );
        engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
    
        return app.exec();
    }
    
    

    然后在QML中简单地调用”Greeting”变量名就能够顺利訪问了。

    import QtQuick 2.2
    import QtQuick.Controls 1.1
    
    ApplicationWindow
    {
        visible: true
         640
        height: 480
        title: qsTr("測试QML于C++的交互")
    
        menuBar: MenuBar
        {
            Menu
            {
                title: qsTr("文件")
                MenuItem
                {
                    text: qsTr("退出")
                    onTriggered: Qt.quit( );
                }
            }
        }
    
        Text
        {
            text: qsTr("本例用来測试QML和C++的交互")
            anchors.right: parent.right
            anchors.bottom: parent.bottom
        }
    
        Text
        {
            text: Greeting
            anchors.centerIn: parent
        }
    }

    
    

    演示程序的截图例如以下:

           本例重要的部分是QQmlContext实例指针。它通过QQmlApplicationEngine::rootContext()来获得,也能够通过QQmlApplicationEngine:: contextForObject(constQObject * object)来获得。

    在QQmlObject创建的时候。都会实例化一个QQmlContext。用来支持为执行环境提供的上下文属性。

           使用上下文属性能够让QML訪问C++数据,那么怎样使用QML来訪问C++的函数呢?这里我们在C++中注冊QML类或者单例来让QML来获得訪问C++函数的机会。首先介绍一下怎样将QML中注冊C++类到QML中。首先须要定义一个C++类继承于QObject,然后这么写:

    #ifndef CPLUSPLUSCLASS_H
    #define CPLUSPLUSCLASS_H
    
    #include <QObject>
    
    class CPlusPlusClass: public QObject
    {
        Q_OBJECT
        Q_PROPERTY( int rating READ rating )
    public:
        explicit CPlusPlusClass( QObject* pParent = Q_NULLPTR ):
            QObject( pParent )
        {
            m_Rating = 5;
        }
    
        Q_INVOKABLE void method( void )
        {
            qDebug( "[C++]%s is called.", __FUNCTION__ );
        }
        int rating( void ) { return m_Rating; }
    private:
        int m_Rating;
    };
    
    #endif // CPLUSPLUSCLASS_H

    然后再main.cpp中须要调用qmlRegisterType()模板函数来注冊C++类到QML中,一个典型的使用方法例如以下:

    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QtQml>
    #include "CPlusPlusClass.h"
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        // 首先注冊一下类
        qmlRegisterType<CPlusPlusClass>(
                    "CPlusPlus.Test",           // 统一资源标识符
                    1,                          // 主版本号
                    0,                          // 次版本号
                    "CPlusPlusType" );          // QML类名称
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
    
        return app.exec();
    }
    
    

           最后在QML中就能够顺利地訪问C++类的属性和方法了:

    import QtQuick 2.2
    import QtQuick.Controls 1.1
    import CPlusPlus.Test 1.0
    
    ApplicationWindow
    {
        visible: true
         640
        height: 480
        title: qsTr("測试QML于C++的交互")
    
        menuBar: MenuBar
        {
            Menu
            {
                title: qsTr("文件")
                MenuItem
                {
                    text: qsTr("退出")
                    onTriggered: Qt.quit( );
                }
            }
        }
    
        Text
        {
            text: qsTr("本例用来測试QML和C++的交互")
            anchors.right: parent.right
            anchors.bottom: parent.bottom
        }
    
        CPlusPlusType
        {
            id: theType
        }
    
        MouseArea
        {
            anchors.fill: parent
            onClicked:
            {
                console.log( "[qml] Rating is: " + theType.rating );
                theType.method( );
            }
        }
    }
    
    

    点击窗口,控制台执行结果例如以下:

    qml: [qml] Ratingis: 5

    [C++]method iscalled.

    假设不想在QML和C++环境中创建多个QObject或者说想要更加方便地訪问C++的方法。那么能够考虑注冊一个单例类,注冊单例类和注冊普通的类差点儿相同,但也有一些显著的差别,首先建立这样一个继承于QObject的类。代码例如以下:

    #ifndef CPLUSPLUSCLASS_H
    #define CPLUSPLUSCLASS_H
    
    #include <QObject>
    
    class CPlusPlusClass: public QObject
    {
        Q_OBJECT
        Q_PROPERTY( int rating READ rating )
    public:
        explicit CPlusPlusClass( QObject* pParent = Q_NULLPTR ):
            QObject( pParent )
        {
            m_Rating = 5;
        }
    
        Q_INVOKABLE void method( void )
        {
            qDebug( "[C++]%s is called.", __FUNCTION__ );
        }
        int rating( void ) { return m_Rating; }
    private:
        int m_Rating;
    };
    
    #endif // CPLUSPLUSCLASS_H

    然后关键在main.cpp中。除了调用qmlRegisterSingletonType()模板函数外。还须要写一个静态全局的注冊函数。代码例如以下:

    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QtQml>
    #include "CPlusPlusSingleton.h"
    
    // 注冊单例函数
    static QObject* CPlusPlusSingletonRegisterFunc(
            QQmlEngine* pQMLEngine,
            QJSEngine* pJSEngine )
    {
        Q_UNUSED( pQMLEngine );
        Q_UNUSED( pJSEngine );
    
        CPlusPlusSingleton* pSingleton = new CPlusPlusSingleton;
        return pSingleton;
    }
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        // 首先注冊一下单例
        qmlRegisterSingletonType<CPlusPlusSingleton>(
                    "CPlusPlus.Test",                   // 统一资源标识符
                    1,                                  // 主版本号
                    0,                                  // 次版本号
                    "CPlusPlusSingleton",               // 单例名称
                    CPlusPlusSingletonRegisterFunc );   // 函数名
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
    
        return app.exec();
    }
    
    

    就这样。C++的部分就完毕了。

    接下来在QML中就非常easy了:

    import QtQuick 2.2
    import QtQuick.Controls 1.1
    import CPlusPlus.Test 1.0
    
    ApplicationWindow
    {
        visible: true
         640
        height: 480
        title: qsTr("測试QML于C++的交互")
    
        menuBar: MenuBar
        {
            Menu
            {
                title: qsTr("文件")
                MenuItem
                {
                    text: qsTr("退出")
                    onTriggered: Qt.quit( );
                }
            }
        }
    
        Text
        {
            text: qsTr("本例用来測试QML和C++的交互")
            anchors.right: parent.right
            anchors.bottom: parent.bottom
        }
    
        MouseArea
        {
            anchors.fill: parent
            onClicked:
            {
                console.log( "[qml] Rating is: " + CPlusPlusSingleton.rating );
                CPlusPlusSingleton.method( );
            }
        }
    }
    
    

    点击窗口。控制台结果例如以下:

    qml: [qml] Ratingis: 5

    [C++]method iscalled.

           大家能够依据须要选择是否在C++中注冊QML类和注冊C++单例来获得相相应的特性。

           在我的第一款独立游戏《吃药了》中,为了顺利地接入广告SDK,须要写C++代码来保证让QML可以訪问到C++的函数,广告显示效果例如以下:

    本文參加了CSDN博文大赛。请我们支持我,选我。

    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    Effective_STL 学习笔记(四十) 使仿函数类可适配
    Effective_STL 学习笔记(三十九) 用纯函数做判断式
    PMP考试大纲
    小技巧
    git 常用命令
    java web的返回值对象
    工作任务-SM敏捷核心思维
    树莓派上手
    spring 公用异常处理
    前端现在版本怎么这么乱
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4617006.html
Copyright © 2020-2023  润新知