zoukankan      html  css  js  c++  java
  • QML与C++集成<二>——<使用C++属性及注册QML类型>

    前言

      在开始讲之前首先讲一个使用属性(setContextProperty)注册类型(qmlRegisterType)的区别,在这主要讲一些我个人工作中的情况,其实二者都是将c++类暴露给QML的方法,只不过在使用时存在一些区别,根据使用方式不同我个人分为C++的形式和QML的定义形式。

    1、C++定义方式(主要使用setContextProperty()函数)

    • a)、比如我们有一个功能单一的Configure类,我们需要把它暴露给QML,在使用之前必须要先创建类对象m_configuration,就是说类实例化一次,QML中可以直接使用这个类,注意功能单一的类只适合该方式;
    • b)、比如我们的业务比较复杂,我们有很多类,若要供QML调用,我们就要写一个总的被调用类Complex(包含所有的业务类),然后实例化一次这个Complex,然后QML中直接使用实例化后的对象;

    两种业务方式的使用方式如下:

    QQuickView viewer;
    viewer.rootContext()->setContextProperty("_configuration",&m_configuration);
    
    
    _configuration便可直接在qml中使用,_configuration自然也是一个全局变量。

    2、QML的方式,(主要使用qmlRegisterType()函数)

      该方式都是使用在业务复杂情况下,还是上面的例子,我们有一堆业务类,这个时候我们使用注册的方式,用在QML中定义的方式去定义各个实例,也就不用再需要一个总类:

    qmlRegisterType<Foo>("App", 1, 0, "Foo");
    qmlRegisterType<Bar>("Bar", 1, 0, "Bar");//注册不可实例化的类型

    我们可以再QML中直接使用Foo去定义实例:

    import App 1.0
    
    Foo {
          bar.baz: "abc"
          Component.onCompleted: print(bar.baz)
      }

    3、二者比较

      与C++方式相比,QML具有如下优势:

    • 变量名前面可以加$(全局变量可用),从而方便区分全局变量和局部变量,这个在C++定义属性的时候是不允许的;

    • 如果某个全局变量(一般是QML对象)构造很慢,可以通过QML中的Loader来很方便异步构造,从而加速程序启动:

    一、在QML中使用C++属性

      QObject子类的所有属性都能够被QML访问,QObject子类使用Q_PROPERTY宏定义一个属性,该宏的作用是向Qt元对象系统注册类的属性,一个类的属性就是类的数据成员,通常会有一个用于读取的READ函数和一个可选的用于修改的WRITE函数。

    该宏定义如下:

     一些常见的申明示例:

    使用我们一般使用setContextProperty()函数,注意和注册的区别,使用一版如下,m_configuration就是一个全局变量,便可在qml中直接使用

    QQuickView viewer;
    viewer.rootContext()->setContextProperty("_configuration",&m_configuration);

     1.1 使用函数和槽

      QML可以有条件地访问QObject子类的函数:

    • 使用Q_INVOKABLE宏标记的public函数
    Q_INVOKABLE bool postMessage(const QString &msg){
    qDebug()<<"postMessage";
    }
    • public槽函数
    public slot:
        void refresh()
        {
            qDebug()<"refresh";  
        }

    1.2 使用信号

      QML代码可以使用QObject子类的任意public信号,QML引擎会为每一个来自QObject子类的信号自动创建一个信号处理器,其命名规则如为:on<Signal>,其中<Signal>为信号的名字,首字母要大写,信号传递的参数通过其名字在信号处理器中使用。

    注意:QML中的信号与前面提到的函数重载不同,如果C++类中具有参数列表不同的多个同名信号,但只有最后一个信号才能被QML访问到。

    二、注册QML类型

       QObject子类可以注册到QML类型系统中,以便在QML程序中作为一个数据类型使用,前面提到的所有操作数据的基础就是先注册Qml类型。可被注册的类分为可实例化和不可实例化两种,注册可实例化的类意味着这个类定义为一个QML对象类型,QML对象类型通过这种注册能够获取这种类型的元数据,以及相关属性信号等操作,注册不可实例化的C++类,意味着这种类型不可实例化,比如我们要把枚举类型暴露给QML,但这个类型本身不需要被实例化。

    2.1 注册可实例化对象类型

      QObject子类都可以注册为QML对象类型,注册成功后这个类就可以在QML代码中像其他类型一样声明和初始化,创建成功后就可以在QML中使用其属性值、函数和信号等特征,注册QObject子类,需要使用qmlRegisterType()函数,下面有两个类Bar,Foo:

    class Bar : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(QString baz READ baz WRITE setBaz NOTIFY bazChanged)
    
      public:
          Bar() {}
    
          QString baz() const { return mBaz; }
    
          void setBaz(const QString &baz)
          {
              if (baz == mBaz)
                  return;
    
              mBaz = baz;
              emit bazChanged();
          }
    
      signals:
          void bazChanged();
    
      private:
          QString mBaz;
      };
    
      class Foo : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(Bar *bar READ bar CONSTANT FINAL)
    
      public:
          Foo() {}
    
          Bar *bar() { return &mBar; }
    
      private:
          Bar mBar;
      };

    我们使用qmlRegisterType将其注册到QML系统类型,该函数需要一个命名空间和版本号:

    qmlRegisterType<Foo>("App", 1, 0, "Foo");
    qmlRegisterType<Bar>();//注册不可实例化的类型

    在QML中使用:

    import App 1.0

    Foo {
          bar.baz: "abc"
          Component.onCompleted: print(bar.baz)
      }

    2.2 注册不可实例化对象类型

      有时需要注册一个不可实例化的对象类型,比如一个C++类:

    • 是接口类型;
    • 一个基类,不需要通过QML代码访问;
    • 仅仅提供一些有用的枚举;
    • 是一个单例,只能使用其唯一的实例,不应该从QML进行实例化。

      注册方法:

    • 使用无参的qmlRegisterType()函数;
    • 使用qmlRegisterInterface()注册指定QML类型名称的Qt接口类型;
    • 使用qmlRegisterUncreatableType()函数
    • 使用qmlRegisterSingletonType()函数 
  • 相关阅读:
    Mysql 创建联合主键
    Shell中的while循环
    shell 日期加减运算
    PHP日期格式转时间戳
    Uber 叫车时,弹出以下代码导致无法打车(An email confirmation has been sent to...),解决办法
    如何让Table显示滚动条
    mySQL中replace的用法
    打豪车应用:uber详细攻略(附100元优惠码)
    svn 命令行创建和删除 分支和tags
    php ob_start()、ob_end_flush和ob_end_clean()多级缓冲
  • 原文地址:https://www.cnblogs.com/laiyingpeng/p/12336848.html
Copyright © 2011-2022 走看看