1. 信号与槽机制(重点,但不是难点)
1.1 机制:
是一种两个对象之间的通信的机制
例如:
鼠标双击-------文件夹图标---------打开文件夹功能
通信的过程:
用户对象
文件夹图标对象
鼠标双击,相当于告诉文件夹(即给文件夹一个信号),我现在想要打开你
文件收到信号,就执行打开文件夹的功能
信号:在QT中信号用函数来进行体现
槽:在QT中槽也是用函数来进行体现
1.2 实现两个对象之间的通信:
提前将两个对象进行绑定(类似于成为你的QQ好友)
1.2.1 QT中提供了绑定的函数(方法):
connect函数原型:
connect(对象1,对象1发出的信号,对象2,处理对象1发出的信号);//来自于QObject
connect(对象1,SIGNAL(信号),对象2,SLOT(槽));
1)对象1:是一个类的实例化,信号的发出者
2)对象1发出的信号:信号,实质上是一个函数,信号是对象1中的函数,信号使用 SIGNAL函数包含
3)对象2:是一个类的实例化,信号的接收者
4)处理对象1发出的信号:槽,实质上也是一个函数,槽是对象2中的函数,槽使用SLOT 函数包含
QObject中的原型:
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnection)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection)
1.3 细节重点
(1)connect函数不仅可以绑定一个信号和槽,也能绑定两个信号
(2)多个信号可以绑定同一个槽函数
(3)一个信号可以绑定多个槽,先绑定哪个槽,哪个槽先执行,后绑定后执行
2. 自定义信号与槽
2.1 信号:在类中需要放置在关键字signals下
例如:
signals:
信号1;
信号2;
......
2.1.1 注意事项:
(1)信号只需要声明,不需要实现
(2)信号的返回值类型是void类型
(3)信号也是可以发生重载
(4)信号的参数个数必须大于等于槽函数的参数个数
2.2 槽:在类中需要放置在关键字slots下
例如:
slots:
槽1;
槽2;
....
2.2.1 注意事项
(1)slots前可以加上修饰符:public、protected、private(与C++中修饰符的作用一致)
(2)槽函数既需要声明,也需要实现
(3)槽函数的返回值类型一般也是设置为void类型
(4)当槽函数的参数与信号的参数一致时,需要满足槽函数的参数类型和信号的参数类型保持一致
2.3 信号的触发:
使用emit关键字对信号进行触发
格式:
emit 信号;//将信号给发送出去
2.4 举例:
2.4.1 练习1
车上的司机,看见红灯亮了之后,车就停下,人过马路
对象1:车
信号:车看见红灯亮了,停下
对象2:人
槽:人就可以过马路
绑定:使用connect函数绑定车和人两个对象
course1
Car.h
#ifndef CAR_H
#define CAR_H
#include <QObject>
class Car : public QObject
{
Q_OBJECT
public:
explicit Car(QObject *parent = nullptr);
signals://写在signals以下的函数都是该类的信号函数
//在qt中信号只需要声明不需要实现
void car_Stop();//表示该函数是Car类的信号
};
#endif // CAR_H
car.cpp
#include "car.h"
Car::Car(QObject *parent)
: QObject{parent}
{
}
people.h
#ifndef PEOPLE_H
#define PEOPLE_H
#include <QObject>
#include <QDebug>
class People : public QObject
{
Q_OBJECT
public:
explicit People(QObject *parent = nullptr);
signals:
public slots://写在slots以下的函数都是该类的槽
void walk();
};
#endif // PEOPLE_H
people.cpp
#include "people.h"
People::People(QObject *parent)
: QObject{parent}
{
}
void People::walk(){
qDebug()<<"人收到车停下的信号,可以过马路"<<endl;
}
mydialog.h
#ifndef MYDIALOG_H
#define MYDIALOG_H
#include <QDialog>
#include <QDebug>
#include <car.h>
#include <people.h>
QT_BEGIN_NAMESPACE
namespace Ui { class MyDialog; }
QT_END_NAMESPACE
class MyDialog : public QDialog
{
Q_OBJECT
public:
MyDialog(QWidget *parent = nullptr);
~MyDialog();
void emit_Car_Stop_Signal();//发送信号函数
private:
Ui::MyDialog *ui;
//实例化方式1
Car* car = new Car;//实例化车
People* people = new People;//实例化人
//实例化方式2
// Car car;
// People people;
};
#endif // MYDIALOG_H
mydialog.cpp
#include "mydialog.h"
#include "ui_mydialog.h"
//练习
// 车上的司机,看见红灯亮了之后,车就停下,人过马路
// 对象1:车
// 信号:车看见红灯亮了,停下
// 对象2:人
// 槽:人就可以过马路
// 绑定:使用connect函数绑定车和人两个对象
MyDialog::MyDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::MyDialog)
{
ui->setupUi(this);
//向控制台打印消息
// qDebug()<<"hello world";
// qDebug("你好,世界");
//1.先实现人车对象的绑定
connect(this->car,SIGNAL(car_Stop()),this->people,SLOT(walk()));//SIGNAL()和SLOT()将你传来的参数转为字符串类型
//2. 在调用信号触发函数
this->emit_Car_Stop_Signal();
}
//析构
MyDialog::~MyDialog()
{
delete ui;
}
void MyDialog:: emit_Car_Stop_Signal(){
//进行信号的触发
emit this->car->car_Stop();
}
main.cpp
#include "mydialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyDialog w;
w.show();
return a.exec();
}
2.4.2 练习2 元旦节发红包
写法1
快到元旦节了,老师给张三发红包,但是老师没张三微信,就先发给李四,让李四转交给张三,张三收到红包后说谢谢老师
course1-1
teacher.h
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
//发送红包的信号函数
void send();
};
#endif // TEACHER_H
teacher.cpp
#include "teacher.h"
Teacher::Teacher(QObject *parent)
: QObject{parent}
{
}
lisi.h
#ifndef LISI_H
#define LISI_H
#include <QObject>
#include <QDebug>
class Lisi : public QObject
{
Q_OBJECT
public:
explicit Lisi(QObject *parent = nullptr);
signals:
void zhuanjiao();//转交红包
public slots:
void jieshou_zhuanjiao();//接收老师的红包转交给张三
};
#endif // LISI_H
lisi.cpp
#include "lisi.h"
Lisi::Lisi(QObject *parent)
: QObject{parent}
{
}
void Lisi::jieshou_zhuanjiao(){
qDebug()<<"lisi代替zhangsan接收到红包,马上转交给zhangsan"<<Qt::endl;
emit this->zhuanjiao();//转交红包,触发信号触发的是李四的信号
}
zhangsan.h
#ifndef ZHANGSAN_H
#define ZHANGSAN_H
#include <QObject>
#include <QDebug>
class Zhangsan : public QObject
{
Q_OBJECT
public:
explicit Zhangsan(QObject *parent = nullptr);
signals:
public slots://槽
void xiexie();//谢谢老师
};
#endif // ZHANGSAN_H
zhangsan.cpp
#include "zhangsan.h"
Zhangsan::Zhangsan(QObject *parent)
: QObject{parent}
{
}
void Zhangsan::xiexie(){
qDebug()<<"zhangsan接收到lisi转交的红包,并说了:谢谢老师的红包"<<endl;
}
mydialog.h
#ifndef MYDIALOG_H
#define MYDIALOG_H
#include <QDialog>
#include <teacher.h>
#include <lisi.h>
#include <zhangsan.h>
QT_BEGIN_NAMESPACE
namespace Ui {
class Mydialog;
}
QT_END_NAMESPACE
class Mydialog : public QDialog
{
Q_OBJECT
public:
Mydialog(QWidget *parent = nullptr);
~Mydialog();
void emit_hongbao_Signal();//发送信号函数
private:
Ui::Mydialog *ui;
//实例化对象
Teacher* tea=new Teacher;
Lisi* lisi = new Lisi;
Zhangsan* zhangsan = new Zhangsan;
};
#endif // MYDIALOG_H
mydialog.cpp
#include "mydialog.h"
#include "ui_mydialog.h"
//练习2
//快到元旦节了,老师给张三发红包,但是老师没张三微信,就先发给李四,让李四转交给张三,张三收到红包后说谢谢老师
Mydialog::Mydialog(QWidget *parent): QDialog(parent), ui(new Ui::Mydialog){//构造
ui->setupUi(this);
//绑定老师与李四
connect(this->tea,SIGNAL(send()),this->lisi,SLOT(jieshou_zhuanjiao()));
//绑定李四与张三
connect(this->lisi,SIGNAL(zhuanjiao()),this->zhangsan,SLOT(xiexie()));
//调用信号触发
this->emit_hongbao_Signal();
}
Mydialog::~Mydialog()
{
delete ui;
}
void Mydialog:: emit_hongbao_Signal(){
//进行信号的触发,触发老师的信号
emit this->tea->send();
}
写法2
course1-2
teacher.h
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
void Tea_send_Red_Package();//老师发送红包信号
};
#endif // TEACHER_H
teacher.cpp
#include "teacher.h"
Teacher::Teacher(QObject *parent)
: QObject{parent}
{
}
lisi.h
#ifndef LISI_H
#define LISI_H
#include <QObject>
class Lisi : public QObject
{
Q_OBJECT
public:
explicit Lisi(QObject *parent = nullptr);
signals:
void lisi_send_Red_Package();//李四转交信号
};
#endif // LISI_H
lisi.cpp
#include "lisi.h"
Lisi::Lisi(QObject *parent)
: QObject{parent}
{
}
zhangsan.h
#ifndef ZHANGSAN_H
#define ZHANGSAN_H
#include <QObject>
#include <QDebug>
class Zhangsan : public QObject
{
Q_OBJECT
public:
explicit Zhangsan(QObject *parent = nullptr);
signals:
public slots:
void receive_Red_Package();//接收红包槽
};
#endif // ZHANGSAN_H
zhangsan.cpp
#include "zhangsan.h"
Zhangsan::Zhangsan(QObject *parent)
: QObject{parent}
{
}
void Zhangsan::receive_Red_Package(){
qDebug()<<"谢谢老师"<<Qt::endl;
}
mydialog.h
#ifndef MYDIALOG_H
#define MYDIALOG_H
#include <QDialog>
#include <teacher.h>
#include <lisi.h>
#include <zhangsan.h>
QT_BEGIN_NAMESPACE
namespace Ui { class Mydialog; }
QT_END_NAMESPACE
class Mydialog : public QDialog
{
Q_OBJECT
public:
Mydialog(QWidget *parent = nullptr);
~Mydialog();
private:
Ui::Mydialog *ui;
//实例化对象
Teacher* tea=new Teacher;
Lisi* lisi = new Lisi;
Zhangsan* zhangsan = new Zhangsan;
};
#endif // MYDIALOG_H
mydialog.cpp
#include "mydialog.h"
#include "ui_mydialog.h"
Mydialog::Mydialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::Mydialog)
{
ui->setupUi(this);
//绑定,在connect中可以绑定两个信号
connect(this->tea,SIGNAL(Tea_send_Red_Package()),this->lisi,SIGNAL(lisi_send_Red_Package()));
connect(this->lisi,SIGNAL(lisi_send_Red_Package()),this->zhangsan,SLOT(receive_Red_Package()));
emit this->tea->Tea_send_Red_Package();//触发信号
}
Mydialog::~Mydialog()
{
delete ui;
}