zoukankan      html  css  js  c++  java
  • 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博文大赛。请我们支持我,选我。

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

  • 相关阅读:
    React元素渲染
    初识JSX
    微信小程序复制文本到剪切板
    微信小程序报错request:fail url not in domain list
    小程序,通过自定义编译条件,模拟推荐人功能
    积分抵扣逻辑
    微信小程序 switch 样式
    tomcat 配置开启 APR 模式
    tomcat8 传输json 报错 Invalid character found in the request target. The valid characters are defined in RFC 3986
    c++数组初始化误区
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4617006.html
Copyright © 2011-2022 走看看