信号与槽是Qt编程的基础,信号与槽在Qt中处理界面各个组件的交互操作时变得更加的直观和简单。
信号
信号(Signal)就是在特定情况下被发射的事件。GUI程序设计的主要内容就是对界面上各个组件的信号进行响应,只需要知道什么情况下发射哪些信号,合理地去响应和处理这些信号就可以了。
槽
槽(Slot)就是响应信号的函数。槽就是一个函数,与一般的C++函数一样,可以定义在类的任何部分(public\private\protected),槽函数可以具有任何参数,也可以被直接调用。槽函数与一般的函数不同的地方在于,槽函数可以与一个信号关联,当信号被发射的时候,与之相关联的槽函数被动的执行。
信号与槽关联是用QObject::connect()函数来实现,基本的格式为:
Qobject::connect(sender,SIGNAL(signal()),receiver,SLOT(slot()));
sender:发射信号的对象的名称;
signal():信号名称,信号可以看做是特殊的函数,需要带括号,有参数时还需要指明参数。
SIGNAL和SLOT是Qt的宏,用于指明信号和槽,并将它们的参数转换为相应的字符串。
例:
QObject::connect(btnClose,SIGNAL(clicked()),Widget,SLOT(Close()));
//将btnClose按钮的clicked()信号与窗体Widget的槽函数close()相关联,当单击btnClose按钮时,就会执行Widget的Close()槽函数。
Qt信号与槽的使用规则:
- 一个信号可以连接多个槽,当一个信号与多个槽相关联时,槽函数按照建立的连接顺序依次执行;当信号和槽函数带有参数时,在connect()函数里要写明参数的类型,但可以不写参数的名称。
- 多个信号可以连接同一个槽;
- 一个信号可以连接另外一个信号,例:
connect(sender,SIGNAL(signal()),sender,SIGNAL(signal()));
//当一个信号被发射时,也会发射另外一个信号,实现某些特殊的功能;
- 严格情况下,信号与槽的参数个数和类型需要一致,至少信号的参数不能少于槽的参数,如果不匹配,会出现编译错误或者运行错误。
- 在使用信号与槽的类中,必须在类的定义中加入宏Q_OBJECT;
- 当一个信号被发射时,与其关联的槽函数通常被立即执行,就像正常调用一个函数一样,只有当信号关联的所有槽函数执行完毕后,才会执行发射信号处后面的代码。
Qt使用信号与槽的机制实现对象间通信,隐藏了复杂的底层实现,完成信号与槽的关联后,发射信号时不需要知道Qt是如何找到槽函数的,信号与槽的执行速度比回调函数稍微慢点,但灵活性要比回调函数强很多。
自定义信号及其使用:
在自己设计的类里可以自定义信号,信号就是在类定义里声明一个函数,但是这个函数无需实现,只需发射(emit).
例如:
class QPerson:public QObject
{
Q_OBJECT
private:
int m_age=10;
public:
void incAge();
signals:
void ageChanged(int value);
}
信号函数必须是无返回值的函数,但是可以输入参数。信号函数无需实现,只需在某些条件下发射信号。例如在incAge()函数中发射信号:
void QPerson::incAge()
{
m_age++;
emit ageChanged(m_age);发射信号
}
当私有变量m_age变化后,发射信号ageChanged(int),表示年龄发生了变换。至于是否有与此信号相关联的槽函数,信号发射者不管。如果在使用QPerson类对象的程序中为此信号关联了槽函数,在incAge()函数里发射此信号时,就会执行相关联的槽函数。至于是否立即执行槽函数,发射信号的线程是否等待槽函数执行完之后再执行后面的代码,与connect()函数设置信号与槽关联时设置的连接类型以及信号与槽是否在同一个线程有关。