您的位置:首页 > 编程语言 > C语言/C++

C++与QML交互2:在QML中调用C++特性

2017-02-25 00:59 218 查看
QML引擎(QQmlEngine)集成了Qt元对象系统,由QObject派生的所有子类的属性、方法和信号等都可以在QML中访问。QObject是子类有多种办法将功能暴露给QML访问:
1、把C++类注册为一个可实例化的QML对象类型,调用方法跟普通的QML类型一样。
2、把C++类注册为一个单例类型,可以在QML中导入单例对象实例
3、把C++类作为上下文属性或者上下文对象嵌入到QML中

在启动QML时,会初始化一个QQmlEngine作为QML引擎,然后使用QQmlComponent对象加载QML文档,QML引擎会提供一个默认的QQmlContext对象作为顶层执行的上下文,用来执行QML文档中定义的函数和表达式。
QQmlEngine::rootContext() 返回当前引擎QML的上下文,唯一的,QQmlContext* QQuickView::rootContext()
QQuickItem* QQuickView::rootObject() 返回当前QQuickView的根节点,也就是QML的根节点

QQmlEngine
QQmlEngine类提供了一个QML引擎,用于管理由QML文档定义的对象层次架构,QML提供了一个默认的QML上下文(根上下文,获取函数QQmlEngine::rootContext())。该上下文是QML表达式的执行环境,并且保证在使用时对象属性能够被正确更新。
QQmlEngine可以将全局设置应用到其管理下的所有QML对象,比如网络通信:QNetworkAccessManager、全局永久(整个程序生命周期)存储的文件路径(资源预加载)等

QQmlContext
QQmlContext提供了对象实例化和表达式执行所需要的上下文环境。所有的QML对象都要在特定的上下文中实例化,所有的表达式都要在特定的上下文中执行。上下文以根上下文为主组成层次结构,子上下文继承父上下文的属性,修改子上下文的属性值可以覆盖父上下文的属性值。
QQmlContext::setContextProperty()能够通过名字将数据显示绑定到上下文,定义、更新上下文的属性
【注意】使用QQmlContext::setContextProperty()显示设置对象的属性会优先于上下文对象的属性

QQmlComponent
QML文档定义的对象类型可以在运行时使用QQmlComponent类进行实例化,QQmlComponent封装了QML组件(component)的定义,可以用于加载QML文档,前提条件是需要QQmlEngine实例化QML文档中定义的对象层次结构。
QQmlComponent实例既可以使用C++直接创建,也可以通过Qt.createComponent()函数在QML代码中创建

QQmlExpression
 动态执行表达式QQmlExpression允许客户端,在C++中利用一个特定的QML上下文执行JavaScript表达式,表达式执行的结果以QVariant的形式返回,并且遵守QML引擎确定的转换规则。

二、在QML中使用C++特性

由于QML引擎与Qt元对象系统的紧密集成,QML可以直接访问QObject子类的属性、方法、信号等。
1、QML可以直接读取和修改C++的属性
2、QML可以通过JavaScript直接调用C++方法
3、QML可以接收C++的信号
由于QML和C++两者运行所需要的上下文环境不同,当QML访问C++数据时,数据的所有权还在C++,特例:就是一个显示的C++函数调用并且返回QObject类型,QML引擎访问获取数据的所有权。Qt提供了两种在QML访问C++的方法:
法1:在C++中创建一个类,注册为QML环境的一个类型,在QML中就可以使用这个类创建对象进行访问。
法2:在C++构建一个对象,把对象通过QQmlContext::setContextProperty()设置到QML的上下文,在QML中可直接使用该对象。

1、把C++创建的类设置到QML上下文

类的要求:(1)QObject类或继承QObject。(2)调用宏Q_OBJECT。这样的类能够进入Qt元对象系统,也会被QML访问。以下是QML经常访问的C++类型
(1)QML访问C++信号、槽
例子:
创建类:                                                                把类加入QML上下文:                                                                              QML中访问C++类
class MakeClass : public QObject                        QQmlEngine engine;   
                                                                           text = qml_make.SetStr("Hello for QML!!!");
{                                                                             MakeClass Cmake;   //类对象,在下边设置上下文                                   qml_make.SlotMake();
    Q_OBJECT                                                         engine.rootContext->setContextProperty("qml_make",&Cmake)
    public:
         Q_INVOKABLE void SetStr(QString str);

    signals:   //C++信号
          void MakeSignal(QString str);

    public slots:  //C++槽函数
          void SlotMake();
};

(2)Q_INVOKABLE 宏修饰函数,会注册到Qt元对象系统中,QML可以直接访问 ${Object}.${method}
定义函数:Q_INVOKABLE void SetStr(QString str);
QML中使用函数:text = qml_make.SetStr("Hello for QML!!!");

(3)Q_ENUMS 宏修饰枚举,会注册到Qt元对象系统中,QML可以直接访问 ${Object}.${method}
定义枚举:Q_ENUMS(m_enum);
QML中使用枚举:text = qml_make.m_enum;

(4)Q_PROPERTY 宏修饰属性,会注册到Qt元对象系统中,QML可以对属性进行访问、修改、属性改变发送信号等操作。
定义属性:Q_PROPERTY(QString Test                //定义一个QString类型的Text属性
                                             READ GetTest         //定义读操作                                                  
                                             WRITE SetText        //定义写操作
                                             NOTIFY SlotTextChanged      //定义关联信号,当属性发生改变时,触发信号
)
QML中使用属性:text = qml_make.GetText;    //调用C++中Text属性的读操作
                         Component.onCompleted: {
                               qml_make.SetText = "Text for QML"    //调用C++中Text属性的写操作
                                      }  

2、把C++对象注册到QML中,当做一个QML对象
QObject 类或 QObject 子类都可以注册到QML中,在QML中当做一个对象类型进行实例化
注册QML类型有多个方法:
(1)qmlRegisterSingletonType()            注册一个单例类型
(2)qmlRegisterType()                             注册一个非单例类型

(3)qmlRegisterTypeNotAvailaible()      注册一个类型用来占位

(4)qmlRegisterUncreatableType()        注册一个具有附加属性类型

例子:

(1)创建类:                                                                                                                                              
class MakeClass : public QObject                                                           
                                           
{                                                                                                              
    Q_OBJECT                                                         
    public:                                                               
         Q_INVOKABLE void SetStr(QString str);

         Q_PROPERTY(QString Test                //定义一个QString类型的Text属性

                                             READ GetTest         //定义读操作     
                                            
                                             WRITE SetText        //定义写操作
                                             NOTIFY SlotTextChanged      //定义关联信号,当属性发生改变时,触发信号

    signals:   //C++信号
          void MakeSignal(QString str);

    public slots:  //C++槽函数
          void SlotMake();
};

(2)在main函数把类注册到QML中,注册函数要放到QML上下文创建之前,否则注册不成功:

qmlRegisterType<MakeClass>("For.Qt.MakeClass" , 1, 0, "MakeClassQml");      //把类MakeClass注册到QML中的包为:For.Qt.MakeClass, 版本:1.0, 类型为:MakeClassQml

QQuickView view; 

view.setSource( QUrl(QStringLiteral("qrc:///main.qml")));  

view.show();  

(3)QML引入并且访问C++对象类型

import For.Qt.MakeClass 1.0 
Item
{
    MakeClassQml{                   
          SetText : "Hello for QML"   //C++属性的写操作
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息