在QML编程中,C++往往用于编写后台逻辑,而QML用于进行界面端编写,因此利用C++与QML进行交互就成为了重点。由于C++与QML交互具有灵活的方式,本文将针对其中一种方式进行讲解。该方式的基本思想为:
- 处理用户交互事件的逻辑在QML中进行
- 接收到用户交互事件后,由QML发送信号至APP
- 在负责业务逻辑的C++文件中找到QML中对应的QObject,并将其信号与指定槽函数绑定
在这个过程中,QML可以被视作一个黑盒子,通过属性、信号和函数与外界进行交互。
在QML中处理用户交互事件
假如我有一个MainMenu.qml,用于实现应用程序的菜单栏,其部分代码如下所示:
1 | // in MainMenu.qml |
里面包含了一个MenuItem,他有一个指定的action,action中代码如下:
1 | Action { |
可以看到,当触发Action之后,qml会发送一条signal,内容为clicked(),此时我们可以在C++中接收这个信号,并进行相应处理。
在负责业务逻辑的C++文件中找到QML中对应的QObject
假设我们现在有了一个engine,并加载了对应的qml文件:
1 | //in main.cpp |
我们现在要在qml中找到能够发送signal的对应的action,其代码如下所示:
1 | QObject *root = engine.rootObjects().first(); |
将信号与槽函数绑定
在接收到信号后,我们所要做的就是将信号与指定槽函数进行绑定即可
1 | QObject::connect(newAction,SIGNAL(clicked()),&w,SLOT(newSlot())); //clicked即为qml中的信号cllicked() |
经过一系列操作,即可实现由QML到C++进行通信的过程
在C++中创建QML对象
有时我们希望能够从C++中向QML发送数据,这种情况需要我们在C++中创建QML可以识别的对象,本节将对C++中创建QML对象的方法进行总结。
继承QQuickItem类
当我们需要创建一个QML对象时,我们需要继承QQuickItem类
1 | class Squircle : public QQuickItem |
属性系统
一个类的属性就是一个类的成员变量,由于QML与C++语法不互通,我们需要一个属性声明系统,让QML能够辨识C++中的成员及成员函数,这个属性系统能够声明C++中的一个成员变量,并提供访问的读/写操作
1 | Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged) |
在上面这行语句中,我们声明了一个类型为qreal的t变量,同时赋予了读方法t
和写方法setT
,NOTIFY为给属性值设置相应信号。
Q_PROPERTY常用格式
此处列举一些常用格式,更常见的请参考参考文献3。
指定读取属性的函数
1 | Class Widget : public QObject |
修改属性的函数
1 | Class Widget : public QObject |
我们限定set函数无返回值且只能有一个输入参数
导出成员变量为属性值
上面两个读/写的属性值都不是类中的成员变量,是凭空声明出来的一个属性值。要想将类中已有的成员变量设置为属性值,需要用 MEMBER
关键字。这样focus
这个属性值就变的可读可写了。要读可以用类自己的 hasFocus()
函数,要写用自带的setFocus()
修改 m_focus
变量就可以了,属性值会自动更新。
1 | Class Widget : public QObject |
虽然READ
、WRITE
、MEMBER
这三个关键字都可以赋予属性值可读可写的特性,但是 READ
、WRITE
和 MEMBER
不能同时使用,赋予可读可写特性一次就够了,不能赋予两次。就好像一个对象不能被析构两次一样。
给属性设置关联信号
1 | Class Widget : public QObject |
这样,在m_focus
发生变化时,可以自动发送信号focusChanged
。