欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

QML调用C++的属性的方法:从QML调用C++中的函数以及连接C++中的信号

程序员文章站 2023-01-15 08:20:29
前言 前面已经介绍了四种从 qml 调用 c++的属性的方法,今天介绍最后一种,从 qml 调用 c++中的函数以及连接 c++中的信号。 调用 c++函数 任何继承于 qobject 类的 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++属性的方法都已经全部介绍完了。