Qt信号槽机制
概述
信号槽机制是Qt中非常标志性的工具。信号和槽本质上都是函数,只不过是更为特殊的函数。
信号槽的简单理解就是某个对象发出信号,而拥有槽的对象接受信号并进行某些操作。但是并不一定每一个信号必须有对应的槽,也并不一定每个槽都需要有信号,二者的耦合性非常低。
可以在任何地方发送信号,不需要知道哪些类发送的信号连接到了哪些类的槽,只需要将信号和槽连接,当某个信号发送时,与之相连的槽(们)就会被执行(和普通的函数调用一样)。
信号和槽之间的关系可以是一对一、一对多、多对一、多对多的关系。
前面提到,信号和槽本质上都是函数,函数就会有函数声明和函数定义,二者的区别稍后再说。这里应该明确的是,信号和槽之间除了响应和被响应的关系,还有数据传递的功能,而参数就是用于参数传递的,一般而言,信号和槽的参数类型应当完全一致,但是槽函数的参数可以少一些,信号多出来的参数将会被忽略。
这里可能会有疑问,槽函数如果是缺省函数,是不是参数就会比信号函数多呢?Qt对此也进行了规定,因为信号和槽都是在运行时进行绑定的,因此缺省函数的实现将会很困难,所以规定槽函数和信号函数都不能使用缺省值。
信号
信号的作用只有一个,就是告知槽函数应该执行了,并且带有槽函数所需要的参数。
信号本身也就是个函数,但是这个函数只能有声明,而绝对不能有定义(也没必要有定义)。
信号函数不能有返回值(void),并且参数列表必须与槽函数一致(只能多不能少)。
在类中,我们通过:
signals:
void funcName(parameter list);
来定义信号,其实Qt自带很多信号,比如点击信号(这是最基本的信号之一),这里写的是自定义的信号。
前面说了,信号可以在任何地方被发送,信号发送的语句为:
emit funcName(parameters);
当信号发送时,槽函数会立即执行,和普通函数调用一样,此时信号和槽会独立于事件循环之外,当槽函数执行完成返回之后,跟在emit
之后的语句会继续执行,如果绑定了多个槽,则会按照connect
的顺序依次执行槽函数,connect
就是连接信号和槽的一个函数。
举例(修改自官方文档):
signals:
void send(int value);
槽
当绑定到槽的信号被发送之后,就会执行槽函数。
槽函数实际上和普通函数没有什么差别,但是槽函数可以被任何发送信号的对象调用,不会受到可见性的制约(访问限制)。
槽函数也可以被定义为虚函数,在某些情况下会非常有效(我目前也还在学习,还不清楚什么时候使用虚函数来定义槽函数比较好)。
前面说,槽函数和普通函数没什么差别,除了参数列表要和信号保持一致之外,没有什么特别约束。槽函数也可以有返回值,也可以被普通调用,唯一不同的就是除了普通调用,还会对信号做出回应。
槽函数声明举例:
public slots:
void funcNameA(parameter list);
int funcNameB(parameter list);
...
举例(修改自官方文档):
public slots:
bool setValue(int value);
我们定义好信号和槽之后,还需要将二者连接在一起,有很多种方法,常见方法是使用QObject::connect
函数,推荐到官方文档查看这个函数的具体用法,因为官方文档真的写的非常非常详细简洁。
举例(修改自官方文档):
TextFinder b, c;
QObject::connect(&b, &TextFinder::send, &c, &TextFinder::setValue);
b.setValue(12);