QT 的信号和槽
在图形界面编程中,很多时候我们希望一个可视对象发生某种变化时通知另一个或几个对
象,再一个地说,我们希望任何一类的对象能和其他对象进行通讯。例如,某个数值显示
窗口负责显示某个滚动条对象的当前数值,当滚动条对象的值发生变化时,我们希望数值
显示窗口能收到来自滚动条对象发送的“数值改变”的信号,从而改变自己的显示数值。
对于类似以上的问题,较早的工具包使用“回调”的方式来实现。回调是指一个函数的指针,
如果你希望一个处理函数同志你一些事件,你可以把另一个函数的指针传递给处理函数。
处理函数在适当的时候会调用回调函数。
采用回调方式实现对象间的通讯有两个主要缺点,首先回调函数不是类型安全的,我们不
能确定处理函数使用了正确的参数来调用回调函数,第二,回调函数和处理函数间的联系
非常紧密,因为处理函数必须知道要调用哪个回调函数。
在 QT 开发环境中,实现对象间的通讯我们有一种称为“信号和槽”的机制可以代替回调函数。
信号和槽机制用于实现对象间的通讯,是 QT 的一个中心特性,恐怕也是 QT 与其它工具
包最不同的地方了。
信号和槽机制就是:当一个特定的事件发生时,一个或几个被指定的信号就被发射,槽就
是一个返回值为 void 的函数,如果存在一个或几个槽和该信号相连接,那在该信号被发射
后,这个(些)槽(函数)就会立刻被执行。
信号和槽机制是类型安全的,一个信号的签名必须与它的接收槽的签名相匹配,这样编译
器就可以帮助我们检查类型是否匹配。信号和槽是很宽松的联系在一起的,一个发射信号
的对象不用考虑哪个槽会接收这个信号,接收信号的槽的所在对象也不知道要连接的信号
是哪个对象发射的。QT 的信号和槽机制可以保证如果你把一个信号和一个槽连接起来后,
槽会在正确的时间使用信号的参数而被调用,信号和槽可以使用任何数量、类型的参数。
QT 的窗口部件已经有很多预定义的信号,也有很多预定义的槽,但我们总是通过继承来
加入我们自己的信号和自己的槽,这样我们就可以处理感兴趣的信号了。凡是从 QObject
类或者它的某个子类继承的所有类都可以包含信号和槽。当某个事件发生后,被指定的信
号就会被发射,它不知道也没有必要知道是否有槽连接了该信号,这就是信息封装。
槽是可以用来接收信号的正常的对象的成员函数,一个槽不知道它是否被其它信号连接。
可以把一个信号和一个槽进行单独连接,这时槽会因为该信号被发射而被执行;也可以把
几个信号连接在同一个槽上,这样任何一个信号被发射都会使得该槽被执行;也可以把一
个信号和多个槽连接在一起,这样该信号一旦被发射,与之相连接的槽都会被马上执行,
但执行的顺序不确定,也不可以指定;也可以把一个信号和另一个信号进行连接,这样,
只要第一个信号被发射,第二个信号立刻就被发射。
下面看看不使用信号和槽和使用信号和槽的两个对象有什么不同。
不使用信号和槽的 C++对象:
class NoSignalClass {
public:
NoSignalClass (void) {}
int value (void) const {return _value;}
int setValue (int value) {_value = value;}
private: