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

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++属性的写操作
    }
}


发布了69 篇原创文章 · 获赞 37 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/xi_gua_gua/article/details/56991367