信号和槽
什么是信号和槽
connect(发送对象,信号,接收对象,槽函数),其中发送信号和槽函数需要用 SIGNAL() 和 SLOT() 来进行声明。
本质是什么
发送对象
就是发送信号的对象,比如按钮。
信号
就是特定的对象发送的事件,比如按钮发送的clicked(),本质上是一个函数。
接收对象
就是接受信号,并执行相应槽函数的对象,比如窗口。
槽函数
信号和槽的规则
如果receiver是this表示什么
表示接受信号的对象是本窗口组件。
如果省略receiver表示什么
connect(ui->pushButton_todayPrice,&QPushButton::clicked,[=](){ui->stackedWidget->setCurrentIndex(0); });
利用lambda表达式实现槽函数
不需要接收对象,直接执行槽函数
信号和槽的建立
ui文件怎么设置信号和槽
1,直接连接
2,转到槽函数
右键转到槽
比如将PushButton转到槽函数,就是选择这个按钮作为发射信号的对象,选择好信号的类型之后就会为这个信号建立一个槽函数。
转到槽,槽函数名称的建立
on+信号对象+信号类型(信号参数)
UI界面实现信号和槽的原理
在UI界面进行的信号和槽的建立不需要自己去连接信号和槽,ui界面实现的功能都会在ui_x.h文件进行代码转换
代码实现信号和槽
连接信号和槽
connect(sender,signalType,receiver,signalDeal);
槽就是signalDeal----信号处理函数
sender----就是发送信号的按钮
connect(btn1,&QPushButton::clicked,this,&QPushButton::close);
注意第二和第四个参数
自定义信号和槽
信号自定义:
槽函数自定义:
5.6以上版本都可以
先连接再触发信号,而不是先触发再连接:
信号的触发--emit:
给槽函数传递参数
当有重载函数时
定义不同类型的函数指针指向各个重载函数地址,无论是信号,还是槽函数,只要是有重载就要定义函数指针,利用函数指针关联起来信号和槽。
以函数指针作为信号函数和槽函数
函数指针一定要用信号和槽所属的对象进行修饰
取函数地址的两种方法
当没有重载函数时
不需要函数指针,即使用参数,直接发送信号的时候传参就可以
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(ui->buttonOk,&QPushButton::clicked,this,&Widget::onBtnClicked);connect(this,&Widget::mysignal,this,&Widget::dealUserSignal);
}Widget::~Widget()
{delete ui;
}void Widget::onBtnClicked()
{QString str = ui->lineEdit->text();if(str.isEmpty())return ;emit mysignal(str); //发送信号
}void Widget::dealUserSignal(QString s)
{qDebug() << "offer = " << s;ui->labelOffer->setText(s);//正常我们按下取消键盘的时候,lineedit上的数据会被清除,那么我们来断开取消按钮和槽函数的链接disconnect(ui->buttonCancel,SIGNAL(clicked()),this,SLOT(on_buttonCancel_clicked()));
}//按下取消按钮的时候
void Widget::on_buttonCancel_clicked()
{ui->lineEdit->clear();
}
connect和disconnect
connect是按键和槽函数建立连接后保持连接
disconnect断开按键和槽函数的连接,让按键不能操作这个槽函数
SIGNAL()和SLOT()
SIGNAL和SLOT是Qt的宏.
优点
可以指定信号和槽函数的参数,不用担心函数重载问题。
缺点
在使用 SIGNAL 和 SLOT 宏时,我们通常会使用字符串来指定信号和槽函数的名称,例如:
connect(sender, SIGNAL(valueChanged(int)), receiver, SLOT(updateValue(int)));
这里的 `SIGNAL(valueChanged(int))` 和 `SLOT(updateValue(int))` 也就是常见的字符串。在预处理阶段这两个宏会被替换为对应定义的代码,在编译期间,Qt 中会将这些宏解析为标准的 C++ 代码,但是也仅仅只是替换,而不会对这两宏的参数,也就是信号和槽函数名是否正确(存在)进行检测,例如:
static const QMetaObject::Connection connect( ... )
{
...
return QMetaObject::Connection(sender->metaObject()->connect(sender, index, receiver, method, connectionType));
}
因此,SIGNAL 和 SLOT 宏并不是作为编译器的一部分来解析的,而是在运行时通过 Qt 的元对象系统来解析的。这意味着,如果使用了错误的信号或槽函数名称,编译器并不会报告任何错误,只有在运行时才会出现错误。这也就是无法进行类型检查的原因。
因为在宏中使用,所以没有类型检查: