在QT中最重要也是必须要掌握的机制,就是信号与槽机制,在MFC上也就是类型的机制就是消息与响应函数机制
在QT中我们不仅要学会如何使用信号与槽机制,还要会自定义信号与槽函数,要自定义的原因是系统提供的信号,在一些情况下是不能完全满足我们的需求的所以就需要我们去自定义信号和槽函数,QT为我们很好的屏蔽了信号是如何找到对应槽函数的底层原理,我们只需要注册和发射信号即可
并且信号与槽更方便的地方在于,这两个东西可以不是同一个对话框的,也就是说这个对话框中发出的信号,它的响应可以在别的对话框中
并且信号与槽可以是多对多的,意思就是一个信号可以关联多个槽函数,一个槽函数也可以被多个信号关联
实现
接下来我们就正式介绍自定义信号与槽的方式,以及这里面的一些坑(亲身经历)
需要注意的是,如果要使用信号和槽就需要在类中添加Q_OBJECT
没有这个信号和槽是不能用的
自定义信号和槽函数的流程
声明信号
信号的声明,需要在signals属性下面,信号和槽函数都必须是无返回值的,可以带参数
例如我们在AddressInfo对话框类中声明一个地址更新的信号代码
cpp
class LocalAddressInfo : public QWidget
{
Q_OBJECT
signals: // 信号
void UpdateAddr(bool BChanged);
}
声明并实现槽函数
槽函数的声明需要在slots属性下面,槽函数要是无返回值的,可以有形参
例如我们在主对话框中声明并实现地址更新的响应槽函数
cpp
class Widget : public QWidget
{
Q_OBJECT
private slots: // 槽函数
// 用户改变客户端的IP地址信息
void UpdateAddr(bool BChanged);
}
注意槽函数是需要实现函数体的
cpp
void Widget::UpdateAddr(bool BChanged)
{
qDebug() << "接收到了信号 BChanged=" << BChanged;
if(BChanged){
m_isAddrUpdate = true;
// IP地址发生改变
m_addr = m_AddrInfo.GetIP();
m_port = m_AddrInfo.GetPort();
InitSocket();
m_isAddrUpdate = false;
}
m_AddrInfo.hide();
}
将信号和指定槽函数进行关联
信号与槽函数的关联需要用到connect函数
connect函数声明
cpp
inline QMetaObject::Connection QObject::connect(const QObject *asender, const char *asignal, const char *amember, Qt::ConnectionType atype);
// asender 信号发送者,所在类的地址
// asignal 发射的信号,该参数可以是信号的地址,也可以是使用SIGNAL()宏指定的信号
// amember 信号响应者槽函数所在的类
// atype 槽函数,该参数可以是槽函数的地址,也可以是使用SLOT()宏指定的槽函数
根据上面我们对connect函数的介绍,信号和槽函数关联的方式有两种
第一种是使用宏来指定信号和槽函数
cpp
// 注册信号与槽
connect(&m_AddrInfo, SIGNAL(UpdateAddr(bool)), this, SLOT(UpdateAddr(bool)));
这里需要注意,如果使用宏来定义信号和槽函数就不要在信号和槽函数上面加上作用域了,意思就是不要SIGNAL(LocalAddressInfo::UpdateAddr(bool))这么写!!!如果这么写注册的信号是不好使的
第二种是使用信号和槽函数的地址
cpp
// 注册信号与槽
connect(&m_AddrInfo, &LocalAddressInfo::UpdateAddr, this, &Widget::UpdateAddr);
发射信号
发射信号需要使用emit,加上信号,如果信号有参数的话需要带上参数值,如何槽函数的参数有默认参数的话可以不需要带上参数值
例如发射地址信息改变信号
cpp
emit UpdateAddr(true);
上面就是整个自定义信号与槽的实现及其使用的讲解
下面我们来扩展一下,信号与槽的一些相关的函数,disconnect()函数用来解除信号与槽的关联、sender()函数用来获取信号的发射者。这里我们就不详细介绍了,大家可以自行了解
到这里QT如何自定义信号和槽就介绍完了
感谢观看学习,大佬们多多指点,愿明天的自己会感谢当下的努力!!!!