在正式介绍
connect
函数前,还需要好好了解信号和槽的概念
所谓信号大家都不陌生,生活中的红绿灯就是一种信号,当出现红灯时,你就接受到了一个红灯信号,然后指向停下来的动作。
同时,如果你也有学习Linux的经历,也会学到信号Signal
,是系统内部的通知机制。
Linux中的信号会涉及到3个要素:
信号和槽是Qt中特有的消息传输机制,他能将相互独立的控件关联起来,比如按钮
和窗口
本身就是两个独立的控件,点击按钮并不会对窗口造成任何影响。通过信号和槽机制,可以将按钮和窗口进行关联,实现点击按钮会使窗口关闭的效果。
演示:
现在你可能看不懂,但当学完connect
函数就没问题了。
信号的本质是事件 信号是由于用户对窗口或者控件进行了某种操作,导致窗口或者控件产生了某个特定的事件,这时Qt对于的窗口类会发送某个信号,以此对用户的操作做出反应。 常见的事件有:
槽的本质就是对信号响应的函数,是一个回调函数。 槽函数与一般的函数不同,槽函数可以与一个信号关联,当信号产生时,关联的槽函数会自动被执行。
信号和槽机制底层是通过函数间的相互调用实现的,每个信号都可以用函数来表示,称为信号函数,每个槽也可以用函数表示,称为槽函数。例如按钮被按下
,这个信号可以用clicked()
函数表示,窗口关闭这个槽可以用close()
函数表示,假如使用信号和槽机制实现点击按钮会关闭窗口
的功能,其实就是使用clicked()
函数调用close()
函数的效果。
信号函数和槽函数通常位于某个类中,和普通的成员函数相比,它们的特别在于:
signals
关键词修饰,槽函数用private slots/protected slots/public slots
修饰。signals/slots
是Qt中在C++的基础上扩展的关键字,专门指明信号函数和槽函数。信号函数的定义自动在编译之前生成,编写Qt应用程序的程序员无需关注。 这种自动生成代码的机制称为元编程,在很多场景中都能见到。
在Qt中,QObject类提供了一个静态成员函数connect()函数,改函数专门用来关联指定的信号函数和槽函数。
connect(const QObject* sender,
const char* singal,
const QObject* receiver,
const char* method,
Qt::ConnectionType type = Qt::AutoConnection)
参数说明:
Qt::AutoConnection
,通常不需要手动设置。connect函数的简单使用,我们要实现的功能就是点击按钮使得按钮上的Hello World
变成Hello Yui
.
开始编辑处理代码: widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->pushButton,&QPushButton::clicked,this,&Widget::handle);
}
Widget::~Widget()
{
delete ui;
}
void Widget::handle()
{
ui->pushButton->setText("Hello Yui");
}
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
button = new QPushButton(this);
button->setText("Hello World");
button->move(200,200);
connect(button,&QPushButton::clicked,this,&Widget::handle);
}
Widget::~Widget()
{
delete ui;
}
void Widget::handle()
{
button->setText("Hello Yui");
}
系统自带的信号和槽通常通过Qt的帮助文档来查询。
就比如我们要查看按钮的信号,在帮助文档中输入QPushButton
然后再去文档中寻找signals
如果没有找到,继续去父类中查找。比如QPushButton
的父类QAbstractButton
connect(const QObject* sender,
const char* singal,
const QObject* receiver,
const char* method,
Qt::ConnectionType type = Qt::AutoConnection)
可以看到的是singal
和method
的类型都是char*
,但是我们传递的却是函数指针,就比如method的函数指针类型是void(*)()
这可对不上,C++可不允许你使用两个不同的指针类型相互赋值。那么这是怎么一回事呢?
以这个代码为例
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
button = new QPushButton(this);
button->setText("Hello World");
button->move(200,200);
connect(button,&QPushButton::clicked,this,&Widget::handle);
}
Widget::~Widget()
{
delete ui;
}
void Widget::handle()
{
button->setText("Hello Yui");
}
现在的写法为
connect(button,&QPushButton::clicked,this,&Widget::handle);
但是在Qt5以前的写法为:
connect(button,SIGNAL(&QPushButton::clicked),this,SLOT(&Widget::handle));
Qt5开始,对上述的写法做出了简化,不需要写SIGNAL和SLOT宏了,给connect提供了重载版本,在重载版本中,第二个参数和第四个参数成了泛型参数,允许我们传入任意类型的函数指针了。 按住ctrl加鼠标左键跳转
此时的connect函数就带有一定的参数检查功能, 如果你传入的第一个参数和第二个参数不匹配,或者第三个参数和第四个参数不匹配,代码会编译出错,这里用到了类型萃取。