一、什么是信号和槽?
我们经常看到的功能,点击一个按钮实现窗口关闭。
这一过程发生了什么?是怎么实现的
按钮相当于一个信号,点击相当于发送一个信号,窗口是个接收者,关闭窗口是个槽函数
信号:各种事件
槽:响应信号的动作
当一个按钮(信号)被触发(发送的信号),某个信号接收到(信号的接收者)就会做出相应的处理动作(槽函数)。他们是怎么建立连接的呢?要想实现这功能我们需要应用到这个api connect()来建立他们四者的关系。
二、connect的实现以及demo实例
1.连接函数 connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));
参数说明:
参数1:信号的发送者
参数2:发送的信号(函数地址)
参数3:信号的接受者
参数4:处理的槽函数(函数的地址)
实现一个按下按钮关闭窗口的demo
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//重置窗口大小
resize(600,400);
//创建一个按钮
QPushButton *btn = new QPushButton("按钮",this);
//设置到对象树中
btn->setParent(this);
//移动按钮
btn->move(100,50);
//点击我的按钮,关闭窗口
connect(btn,QPushButton::clicked,this,QWidget::close);
}
Widget::~Widget()
{
delete ui;
}
2、松散耦合
信号和槽的优点:松散耦合,信号的发送端和接收端本身是没有关联的,通过connect连接,将两端耦合在一起。
三、自定义信号和槽
3.1、自定义信号实现说明
1、写到signal下
2、返回void
3、需要声明,不需要实现
4、可以有参数,可以重载
3.2、自定义的槽函数实现说明
1、返回void
2、需要声明,也需要实现
3、可以有参数,可以重载
4、可以写到public slot下或者public或者全局函数(早期QT版本,必须要写到public slots,高级版本可以写到public或者全局函数)
1.自定义一个信号和槽函数demo实现:下课了,小明触发一个信号,想去打游戏,小张响应信号,一起打王者
//创建两个类,Ming,Zhang 基类是QObject
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//创建一个小明对象
this->xm = new Ming;
//创建一个小张对象
this->xz = new Zhang;
connect(xm,Ming::playGame,xz,Zhang::playLol);
classIsOver();
}
//封装一个下课函数,调用emit触发玩游戏的信号
void Widget::classIsOver()
{
emit xm->playGame();
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include "zhang.h"
#include "ming.h"
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
Ming *xm;
Zhang *xz;
void classIsOver();
};
#endif // WIDGET_H
ming.h
#ifndef MING_H
#define MING_H
#include <QObject>
class Ming : public QObject
{
Q_OBJECT
public:
explicit Ming(QObject *parent = 0);
signals:
void playGame();
public slots:
};
#endif // MING_H
zhang.h
#ifndef ZHANG_H
#define ZHANG_H
#include <QObject>
class Zhang : public QObject
{
Q_OBJECT
public:
explicit Zhang(QObject *parent = 0);
signals:
public slots:
void playLol();
};
#endif // ZHANG_H
zhang.cpp
#include "zhang.h"
#include <QDebug>
Zhang::Zhang(QObject *parent) : QObject(parent)
{
}
void Zhang::playLol()
{
qDebug()<<"一起打王者";
}
2.自定义带参一个信号和槽函数demo实现:下课了,小明触发一个信号,想去打游戏,小张响应信号,一起打王者,角色是安琪拉
//创建两个类,Ming,Zhang 基类是QObject
widget.cpp
#include <QPushButton>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//创建一个小明对象
this->xm = new Ming;
//创建一个小张对象
this->xz = new Zhang;
//用函数指针传递函数地址
void(Ming:: *mingSignal)(QString) = Ming::playGame;
void(Zhang:: *zhangSignal)(QString) = Zhang::playLol;
connect(xm,mingSignal,xz,zhangSignal);
classIsOver();
}
//封装一个下课函数,调用emit触发玩游戏的信号
void Widget::classIsOver()
{
emit xm->playGame("安琪拉");
}
Widget::~Widget()
{
delete ui;
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include "zhang.h"
#include "ming.h"
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
Ming *xm;
Zhang *xz;
void classIsOver();
};
#endif // WIDGET_H
ming.h
#ifndef MING_H
#define MING_H
#include <QObject>
class Ming : public QObject
{
Q_OBJECT
public:
explicit Ming(QObject *parent = 0);
signals:
void playGame(QString roleName);
public slots:
};
#endif // MING_H
zhang.h
#ifndef ZHANG_H
#define ZHANG_H
#include <QObject>
class Zhang : public QObject
{
Q_OBJECT
public:
explicit Zhang(QObject *parent = 0);
signals:
public slots:
void playLol(QString roleName);
};
#endif // ZHANG_H
zhang.cpp
#include "zhang.h"
#include <QDebug>
Zhang::Zhang(QObject *parent) : QObject(parent)
{
}
void Zhang::playLol(QString roleName)
{
qDebug()<<"一起打王者,角色:"<<roleName.toUtf8().data();
}
**四、QString 转char ***
//QString转char方法:先转成QByteArray(.toUtf8()) .data()再转char
qDebug()<<"打王者,角色是:"<<roleName.toUtf8().data();
}
五、信号和槽之间的关系
1、信号可以连接信号
2、信号可以连接多个信号
3、一个信号可以连接多个槽
4、多个信号可以连接同一个槽
5、信号和槽的参数一一对应
6、信号和槽的参数个数 是不是要一致?未必,信号的参数个数可以多于槽函数的参数个数
六、Lambda表达式
C++中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作。
1.[]标识符 匿名函数
2.= 值传递
3.&引用传递
4.()参数
5.{}实现体
6.mutable修饰值传递变量,可以修改拷贝出的数据,改变不了本体
7.返回值[M]->int []
利用lambda表达式,实现点击按钮关闭窗口的demo
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
resize(600,400);
//创建一个按钮
QPushButton *btn = new QPushButton("按钮",this);
//设置到对象树中
btn->setParent(this);
//移动按钮
btn->move(100,50);
//点击我的按钮,关闭窗口
connect(btn,QPushButton::clicked,this,[=](){
this->close();
qDebug()<<"窗口关闭";
});
}
Widget::~Widget()
{
delete ui;
}