QML调用C++的属性的方法:从QML调用C++中的函数以及连接C++中的信号
前言
前面已经介绍了四种从 qml 调用 c++的属性的方法,今天介绍最后一种,从 qml 调用 c++中的函数以及连接 c++中的信号。
调用 c++函数
任何继承于 qobject 类的 c++类型都可以在 qml 中进行调用,调用c++方法有两个前提:
c++类继承于 qobject 类 将要调用的方法必须是 public 类型的
满足以上两个条件就可以对 c++方法进行调用,但是调用的函数只有两种:
通过q_invokable宏声明 公有的槽函数
ok,写得已经很清楚了, 下面来看看示例:
同样是在之前的 demo 中进行修改。
class student : public qobject { q_object public: explicit student(qobject *parent = nullptr); ~student(){} q_invokable bool setheight(int h){ qdebug() << __function__ << "call the c++ function with: " << h; return true; } public slots: void onrefresh(){ qdebug() << "call the c++ slot."; } };
在 main 函数中进行注册上下文属性:
student student; engine.rootcontext()->setcontextproperty("student", &student);
然后在 qml 中进行调用。
button{ width: 30 height: 30 text: "click me" onclicked: { var ret = student.setheight(100) console.log("c++ result of setheight:",ret) student.onrefresh() } }
运行程序,点击按钮,程序输出如下:
setheight call the c++ function with: 100 qml: c++ result of setheight: true call the c++ slot.
以上示例说明了从 qml 调用q_invokable宏标记的公有函数以及公有槽函数。
qml支持重载c ++函数的调用。如果有多个具有相同名称但参数不同的c ++函数,则将根据提供的参数的数量和类型调用正确的函数。
当从qml中的javascript表达式访问时,从c ++方法返回的值被转换为javascript值。
连接 c++的信号
从 qml 连接 c++中的信号就更简单了,其实在第一篇文章中已经用过了信号的连接,这里再单独提出来讲一遍,和上面一样,也需要满足 c++是继承于 qobject 类型才可以,在 qml 中连接信号,格式如下:
on < singles >:
其中,signals 是 c++中定义的信号名称,在 qml 中连接的时候,只需要在信号名前面加 on,然后信号的第一个字母大写,最后加一个冒号,就 ok 了, 我们来看看实际的示例:
同样是在上面的代码中进行修改:
class student : public qobject { q_object q_property(qstring name read getname write setname notify signamechanged) public: explicit student(qobject *parent = nullptr); ~student(){} q_invokable bool setheight(int h){ qdebug() << __function__ << "call the c++ function with: " << h; return true; } void setname(const qstring & name){ if(name != m_name){ m_name = name; emit signamechanged(m_name); } } qstring getname() const {return m_name;} signals: void signamechanged(qstring name); public slots: void onrefresh(){ qdebug() << "call the c++ slot."; } private: qstring m_name; };
在之前的基础上,这里多增加了一个信号,属性定义在之前的文章中已经介绍过了,就不在多说。
然后在 qml 中进行调用:
window { visible: true width: 640 height: 480 label{ anchors.centerin: parent text: student.name } connections{ target: student onsignamechanged:{ console.log("student name changed",name) } } component.oncompleted: { student.name = "xiaoming" } button{ width: 30 height: 30 text: "click me" onclicked: { var ret = student.setheight(100) console.log("c++ result of setheight:",ret) student.onrefresh() } } }
我们在页面加载完成后设置了 student 的 name 属性:
component.oncompleted: { student.name = "xiaoming" }
然后通过connections连接了信号,最后我们来看看输出消息:
qml: student name changed xiaoming
与属性值和方法参数一样,信号参数必须具有qml引擎支持的类型; (使用未注册的类型不会生成错误,但参数值将无法从处理程序访问。)
请注意,名称相同但参数不同的信号不能相互区分的,所以尽量不要使用同名的信号。
代码已经很简单了,至于信号的连接方式,后期再单独写文章进行介绍。
至此,所有的从 qml 调用 c++属性的方法都已经全部介绍完了。
上一篇: 浅谈Hibernate n+1问题