信号与槽是一种高级接口,称为对象之间的通信,它是QT的核心特性(有点类似MFC的消息机制)。
信号
当QPushButton,在鼠标单击后发射clicked()时,某个信号指示客户或所有者发送其内部状态发生变化,信号将被一个对象发射。
- 信号只声明不实现。
signals:
void showDlg(); /*返回类型都是void*/
信号可以通过关键字emit来发射
emit showDlg();
槽函数
插槽函数可以像普通的C ++成员函数一样,可以被正常调用,也可以与信号关联。当关联的信号被发射时,这个插槽函数就会被调用。
槽函数也存在权限:
- public slots:任何对象都可将将信号与之相连接。
- protected slots:当前类及其子类可以将信号与之相连接。
- private slots:只有类自己可以将信号与之相连接。
信号与槽函数的连接
static QMetaObject::Connection connect(const QObject *sender,\
const char *signal,const QObject *receiver, \
const char *member, Qt::ConnectionType = Qt::AutoConnection);
- 发件人:信号发射者对象
- 信号:信号
- 接收器:信号接收者
- 成员:槽函数
- ConnectionType:连接类型。默认自动连接
一个信号连接一个槽
一个信号要和槽函数成功相连,他们的参数必须具有相同的顺序和相同的类型,或者允许信号的参数比槽函数多,槽会自动忽略掉多余的参数而进行调用
QObject::connect(btn, SIGNAL(clicked(bool)), this, \
SLOT(btnAddClicked()));
一个信号可以连接多个槽
使用QObject :: connect将一个信号连接到多个槽时,当信号发射时,将按声明联系时的顺序顺序调用
connect(A,SIGNAL(recvFinshed(const QList<QByteArray> &)), B , \
SLOT(onRecvFinsed(const QList<QByteArray> &)));
connect(A,SIGNAL(recvFinshed(const QList<QByteArray> &)), C ,\
SLOT(onRecvFinsed(const QList<QByteArray> &)));
多个信号连接同一个槽函数
当多个信号连接到同一个槽上时,每个信号的发送,都会调用这个槽。
connect(A,SIGNAL(recvFinshed(const QList<QByteArray> &)), C ,\
SLOT(onRecvFinsed(const QList<QByteArray> &)));
connect(B,SIGNAL(recvFinshed(const QList<QByteArray> &)), C , \
SLOT(onRecvFinsed(const QList<QByteArray> &)));
一个信号可以和另外一个信号连接
当发射第一个信号时,也会把第二个信号发送出去
//两个信号相连
connect(&a,SIGNAL(valueChanged(QString)),&b,\
SIGNAL(valueChanged(QString)));
//再建立b与c的连接
connect(&b,SIGNAL(valueChanged(QString)),&c,\
SLOT(setValue(QString)));
//下面的操作同时发送了信号a.valueChanged与b.valueChanged
a.setValue("this is A");
//从而信号b.valueChanged被槽c.setValue所接收
连接可以被除去
去除B与C之间的连接
disconnect(B,SIGNAL(recvFinshed(const QList<QByteArray> &)), C ,\
SLOT(onRecvFinsed(const QList<QByteArray> &)));
自定义信号
所有继承QObject或者它的子类都可以包含信号与槽,所以我们自定义的类一定要继承QObject(或者其子类)。所有包含信号与槽的类都必须声明Q_OBJECT宏
以下是简单的结构,代码细节暂时忽略。
......
class classname : public QObject
{
Q_OBJECT //必须包含
public:
classname ()
public slots:
void slotfunction();
signals:
void signalxxx();
}
......
总结
- 信号与槽机制本身就是一种通信机制
- 和MFC消息机制有相似地方
- 槽函数本质上是一种回调函数。不过信号与槽可以一对多或者多对一,降低了对象的耦合度
- 在看嵌入式中断回调机制,是不是也有相通的地方。不过中断涉及到操作系统调度,会抢占一些操作。