前言
简单了解了Qt,现在来学习Qt中的 信号和槽
信号和槽
在 Qt 当中,用户和控件的每一次交互过程称为一个事件;例如:用户点击按钮、用户关闭窗口。这些事件都会发出一个信号
Qt中所有的控件都具有接受信号的能力,并且一个控件还可以接受多个不同的信号。对于接收到的每个信号,控件就会做出相应的动作。
对于接受到的信号,所做出的相应动作,就是 槽(槽函数)
在Qt中,事件 是用户与控件的交互行为(如点击按钮、输入文本),而控件在事件发生后会发出信号 ;槽 是响应信号的函数------信号是"通知",槽是"动作",二者通过connect绑定,实现"事件触发→信号发送→槽函数执行"的逻辑链。
信号和槽,是Qt特有的消息传输机制,能将相互独立的控件关联起来。
例如:点击按钮,没有任何反应;就可以对
cdicked信号,设置对应的槽函数,这样在点击时就会做出相对应的动作。

connect 的使用
在之前,我们只是创建出来一个控件(文本、按钮等),实际运行起来,点击按钮是没有任何反应的。
那是因为我们并没有对该控件产生的信号关联槽函数,也就是没有对该控件产生的信号做处理。
要将控件产生的信号关联槽函数就要使用connect。
对于
connect函数,包含4个需要传递的参数:
sender:表示产生信号的控件(谁产生的信号)signal:表示产生的什么信号(产生的什么信号)receiver:表示信号的接受方(谁处理这个信号)method:表示信号的处理方法(如何处理这个信号)
这里创建一个按钮,对该按钮产生的clicked信号(按下)关联槽函数(Widget::close)关闭窗口
cpp
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton* button = new QPushButton(this);
button->move(200,200);
connect(button,&QPushButton::clicked,this,&Widget::close);
}
这样,在按下按钮时,整个程序窗口就会被关闭。
自定义槽函数
上述关联的槽函数是Widget::close,是Qt内置的槽函数;
当然,我们也可以自己实现一个槽函数,并于某个控件产生的信号关联。
例如,这里自定义一个槽函数,实现按下按钮,使得按钮上的文字在hello qt和hello world直接切换
cpp
//在Widget.h在声明
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
public slots:
void handle();
private:
Ui::Widget *ui;
};
//在Widget.cpp中定义
void Widget::handle()
{
if(ui->pushButton->text() == "hello qt")
ui->pushButton->setText("hello world");
else
ui->pushButton->setText("hello qt");
}
//在Widget构造函数中关联槽函数
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->pushButton,&QPushButton::clicked,this,&Widget::handle);
}
这样,就对于创建的按钮产生的clicked信号关联了自定义槽函数。
无论是使用代码创建QPushButto对象,还是通过form图形化界面创建的按钮都可以使用connect关联槽函数。
自定义槽函数 ,需要在声明时带上
public slots字段。(Qt 5以后版本也可以不用带该字段)
自定义信号
在Qt当中,内置了非常多的信号和槽函数,这样内置的信号槽可以满足大部分的开发需求。
我们也可以自定义信号,并且对于自定义的信号关联槽函数。
自定义信号,需要带上
signals:字段(Qt 5 以后版本可以不用带该字段)自定义信号只需声明,无需定义
cpp
//Widget.h
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
signals:
void mysignal();
private:
Ui::Widget *ui;
};
自定义信号,也可以关联槽函数(内置和自定义槽函数都可以)
cpp
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
connect(this,&Widget::mysignal,this,&Widget::close);
}
到这里,我们会发现:自定义了信号,关联了槽函数;
但是没有触发信号啊,运行起来没有任何反应啊
触发信号
对于内置信号,例如clicked,用户按下按钮就会触发;
而自定义信号,用户操作不会触发我们自定义的信号,就需要我们手动触发。
触发信号的关键字 :emit(Qt 5 以后版本也可以省略该字段)
cpp
emit mysignal();
到这里,我们会发现:所谓的信号和槽,不就是类中的不同函数吗。
参数问题
对于自定义信号和槽,可以给其设定参数。
对于带参数的信号,在关联槽函数时就要注意:
- 参数类型必须相同。
- 参数个数可以不同,信号的参数个数必须大于或等于槽函数的参数个数。
form自动生成槽函数
我们可以使用form创建控件,当然也可以使用form来生成对应的槽函数。

这样就可以自动生成对应槽函数的声明和定义
通过这种方式创建的槽函数是不需要调用connect关联的
这种方式生成的槽函数,命名是有规律的:on_objectName_signal
objectName:创建控件时,控件属性objectName对应的值
signal:所关联的信号名称
disconnect取消关联
connect可以关联槽函数,而distconnect就取消信号和槽函数的关联。
disconnect的用法和connect一样,需要传递4个参数。
其常用在取消关联某一个槽函数,转而关联另外一个槽函数。
lambda 简化槽函数
在C++11中,存在lambda表达式,这里在调用connect,传递槽函数时,就可以使用lambda来充当槽函数。
对于Qt 5 以后的版本,默认按照 C++ 11来进行编译的;而对于旧版本,就需要在.pro文件中加上C++11的编译选项。