文章目录
1、信号和槽机制
信号与槽用于两个对象之间,当一个部件发生改变时,希望其他部件也能了解到该变化,也希望任何对象与其他对象进行通信。
-
Qt封装了具体操作系统的消息机制,遵循经典的GUI消息驱动事件模型。 消息驱动机制
-
QT定义了与操作系统消息相关的自己的概念,即信号与槽。
-
信号signal是由操作系统产生的消息。
-
槽slot是程序中的消息处理函数。
-
connect将系统消息绑定到消息处理函数。
-
信号到槽的连接必须发生在两个QT对象间。
bool QObject::connect (
const QObject * sender, //发生对象
const char * signal, //消息名
const QObject * receiver, //接收对象
const char *method, //接收对象的成员函数
Qt::ConnectionType type = Qt::AutoConnection )
eg:
connect(ui->btn, &QPushButton::clicked, this, &MainWindow::change_state);
connect(ui->btn, SIGNAL(clicked()), this, SLOT(change_state()));//qt4
信号和槽机制的特色和优越性:
-
信号和槽机制是类型安全的,相关联的信号和槽的参数必须匹配;
-
信号和槽是松耦合的,信号发送者不知道也不需要知道接受者的信息;
-
信号和槽可以使用任意类型的任意数量的参数。
虽然信号和槽机制提供了高度的灵活性,但就其性能而言,还是慢于回调机制的。回调函数 性能差异在应用程序中还是很难体现出来的
2 、QT中的相关的关键字
- SIGNAL用于指定消息名
- SLOT用于指定消息处理函数名
- Q_OBJECT所以自定义槽的类必须在类声明的开始处加上Q_OBJECT
- slots用于在类中声明消息处理函数
- signals用于在哪种声明信号
3、 使用信号和槽应该注意
需要继承自QObject或其子类;
在类声明的最开始处添加Q_OBJECT宏;
槽中的参数的类型要和信号的参数的类型相对应,且不能比信号的参数多;
信号只用声明,没有定义,且返回值为void类型。
声明一个信号要使用signals关键字,在signals前面不能使用public、private和protected等限定符
因为只有定义该信号的类及其子类才可以发射该信号。- 一个信号可以关联到多个槽上,多个信号也可以关联到同一个槽上,如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地执行,但是它们执行的顺序是随机的,无法指定它们的执行顺序。
槽是普通的成员函数,也有访问权限。
- 槽的访问权限决定了谁能够与其相关联。同普通的C++成员函数一样,槽函数也分为三种类型,即public slots、private slots和protected slots
- public slots:使用publicslots声明的槽表示任何对象都可将信号与之相连接。在组件编程中,可以创建彼此互不了解的对象,将它们的信号与槽进行连接以便信息能够正确的传递。
- protected slots:使用protected slots声明的槽表示当前类及其子类可以将信号与之相连接。适用于那些槽,它们是类实现的一部分,但是其界面接口却面向外部。
- private slots:使用private slots声明的槽表示只有类自己可以将信号与之相连接,适用于联系非常紧密的类。
槽函数就是一个普通函数,在没有与信号一起使用的时候,可以以普通成员函数的方式来使用
4 、信号与槽三种使用方式:
1、转到槽(快捷方式)
鼠标右键点击发送信号的控件,选择转到槽,选择对应的信号,会在.cpp中生成槽函数,在槽函数内部编写要执行的代码(行为)。
2、自定义槽函数和连接函数
在接收信号的类里面声明槽函数,槽函数的定义跟类的普通成员函数定义方式一样。
在发送信号和接收信号的对象建立之后代码中使用connet函数进行信号与槽函数的连接
3、自定义信号、槽函数和连接函数
在发送信号的类中自定义一个信号,在声明信号的类或派生类发送.
在接收信号的类里面声明槽函数,槽函数的定义跟类的普通成员函数定义方式一样。
在发送信号和接收信号的对象建立之后代码中使用connet函数进行信号与槽函数的连接
自动生成的槽函数命名规范:on_对象名称_对象信号(),在后两种方式中如果槽函数按照这样的命名方式,就可以不写连接。
5、信号与槽使用小结
1、信号声明位置,信号发送位置?
信号声明在发送信号的类中声明(.h)中
①自定义一个信号
signals:://信号不能像普通函数一样使用,也不需要权限声明
void mysignal();//信号不需要定义
②发送信号
emit mysignal();
2、槽函数声明位置,槽函数定义位置?
接收信号的类中声明槽函数(.h)
private slots://槽函数在类中的声明
void myslot();//槽函数的定义跟类的普通成员函数定义方式一样
//槽函数定义
void MainWindow::myslot()
{
ui->label_2->setText("完成设置");
}
匿名函数方式
qt5支持 c++11中的lambda表达式:
connect(btn,&QpushBtton::clicked,[=](/*参数*/){
//函数体
});
3、connect建立信号和槽函数的链接?
在同时能够看到信号发送者和信号接收者的地方
//绑定信号和槽函数
// connect(this, SIGNAL(mysignal()), this, SLOT(myslot()));
connect(this, &MainWindow::mysignal, this, &MainWindow::myslot);
6、信号与槽传递数据
通过参数来传递
void send_data(QString msg); void recv_data(QString msg);
注意:
(1)信号不带参数,槽函数一定不能带参数
(2)信号带参数,槽函数可以不带参数,如果槽函数带参数,得保证类型和信号的参数类型一致
(3)信号参数个数可以是多个,槽函数可以没有,也可以有多个(顺序要与信号的参数一致),也可以有其中的某个
7、断开连接
当信号与槽没必要进行保持关联时,可以使用disconnect函数来断开连接
bool QObject::disconnect (
const QObject * sender,
const char * signal,
const QObject * receiver,
const char *method )
disconnect函数断开发送者中的信号与接收者中的槽函数之间的关联。
在disconnect函数中0可以用作一个通配符,分别表示任何信号、任何接收对象、接收对象中的任何槽函数。但是发射者sender不能为0,其它三个参数的值可以等于0。
①断开与某个对象关联的任何对象
disconnect(sender,0,0,0);
//sender->disconnect();
②断开与某个特定信号的任何关联
disconnect(sender,SIGNAL(mySignal()),0,0);
//sender->disconnect(SIGNAL(mySignal()));
③断开两个对象之间的关联
dixsconnect(sender,0,recevier,0);
//sender->disconnect(recevier);