目录
信号槽
信号槽是Qt框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出的信号是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。
connect(sender,signal,receiver,slot);
- sender:发出信号的对象
- signal:发送对象发出的信号(函数地址)
- receiver:接收信号的对象
- slot:接收对象在接收到信号之后所需要调用的槽函数地址
优点:
松散耦合:信号的发送端和信号的接收端本身是没有关联的,通过connect函数将两端耦合在一起。
标准信号槽
练习:点击按钮关闭窗口
myWidget::myWidget(QWidget *parent)
: QWidget(parent) //调用父类构造函数
{
//创建一个按钮
QPushButton *btn = new QPushButton;
//btn->show(); //以顶层方式弹出窗口控件
//让btn依赖在myWidget窗口中
btn->setParent(this); //this指当前窗口
btn->setText("关闭");
btn->move(100,100);
//点击按钮关闭窗口
//参数1:信号发送者 参数2:发送的信号(函数地址) 参数3:信号接收者 参数4:处理槽函数地址
connect(btn,&QPushButton::clicked,this,&QWidget::close);
}
myWidget::~myWidget()
{
}
这里的clicked按钮中的标准信号,close关闭窗口函数是标准槽函数。
自定义信号槽
当Qt提供的信号和槽函数无法满足需求时,就需要用到自定义信号槽,使用emit来发出信号。
练习:定义老师和学生类继承QWidget,老师发出下课信号,学生响应请吃饭
teache.h
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
//自定义信号,写道signals下
//返回值时void,秩序申明,不需要实现
//可以有参数,可以重载
void hangry();
public slots:
};
#endif // TEACHER_H
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
signals:
public slots:
// 早期Qt版本需要写到public slots下,高级版本可以写到public或全局下
// 返回值为void,需要声明,也需要实现
// 可以有参数,可以发生重载
void treat();
};
#endif // STUDENT_H
student.cpp
#include "student.h"
#include <QDebug>
Student::Student(QObject *parent) : QObject(parent)
{
}
void Student::treat()
{
qDebug()<<"请老师吃饭";
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "teacher.h"
#include "student.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
Teacher *te;
Student *st;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>
//Teacher类
//Student类
//下课后 老师会触发一个信号,饿了,学生响应信号,请客吃饭
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//创建老师对象
this->te = new Teacher(this);
//创建学生对象
this->st = new Student(this);
//连接老师和学生
connect(te,&Teacher::hangry,st,&Student::treat);
//发出信号
emit te->hangry();
}
Widget::~Widget()
{
delete ui;
}
信号槽的重载
重载的信号槽,需要构造信号和槽函数对应的重载函数的指针,让信号在连接时可以找到对应的重载函数。
练习:定义老师和学生类继承自QWidget,老师发出下课信号,饿了,想吃宫保鸡丁,学生响应请老师吃宫保鸡丁。
在teacher.h中增加有参的信号
void hangry(QString foodName);
在student.h中增加有参的槽函数
void treat(QString foodName);
在student.cpp中实现带参数的重载槽函数
void Student::treat(QString foodName)
{
//qDebug打印Qstring时带引号,转为char *就不带引号、、
//转换:先转成QByteArrey,再转char * ->foodName.toUtf8().data()
qDebug()<<"请老师吃:"<<foodName.toUtf8().data();
}
在widget.cpp中连接信号槽
//连接重载的信号和槽
//指针 -> 指向地址
//函数指针 -> 指向函数的指针
void(Teacher:: *teacherSignal)(QString) = &Teacher::hangry;
void(Student:: *studentSlot)(QString) = &Student::treat;
connect(te,teacherSignal,st,studentSlot);
//发出信号
emit te->hangry("宫保鸡丁");
可以用disconnect()函数取消信号的槽连接。