Qt信号和槽机制
什么是信号和槽
当某个事件发生,就执行一个操作
- 发生的事情就是信号,执行的操作就是槽(函数)
- 给二者加上主体:信号发出者发出信号,信号接收者执行操作
- 将二者联系起来(松耦合):connect()函数
connect(sender,signal,receiver,slot);
/*
参数解释:
sender:发出信号的对象
signal:发送对象发出的信号
receiver:接收信号的对象
slot:接收对象在接收到信号之后所需要调用的函数(槽函数)
*/
信号函数查询:
Qt帮助文档——>搜信号发送控件对象所属的类——>查看Signals
槽函数查询同理:信号接收对象所属的类——>Public Slots
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-im80fCsV-1644556765715)(image-20211115100117433.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8UBsGNof-1644556765716)(image-20211115100339993.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-exBZZKl9-1644556765718)(image-20211115100402926.png)]
- clicked 鼠标点击后
- pressed 鼠标按下后
- released 鼠标释放后
- toggled 状态切换后
实例代码:
// 点击按钮则关闭窗口
#include "mainwindow.h"
#include<QPushButton>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// 创建按钮
QPushButton * btn = new QPushButton;
btn->move(100,100);
btn->setText("关闭窗口");
btn->setParent(this);
btn->resize(100,50);
resize(800,800);
setFixedSize(800,800);
// 建立连接
connect(btn,&QPushButton::clicked,this,&QWidget::close);
}
MainWindow::~MainWindow()
{
}
自定义信号和槽
- 确定信号发出者和信号接收者
- 在信号发出者所在类中自定义信号(声明一个无返回值函数,不需要实现)
- 在信号接收者所在类中自定义槽函数(声明一个无返回值函数,需要实现)
- 利用connect()函数建立连接
- 利用关键字emit调用信号函数
实例:老师发出下课信号,学生去吃饭
- 新增老师和学生类,因为不是控件,直接去继承最高的QObjcet类
- 在老师类中添加信号:
// 文件techer.h下内容
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
/*
自定义信号写在这下面
无返回值,只声明,不需要实现
可以有参,可以重载
*/
// 声明一个下课信号
void class_over();
};
#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:
/*
5.4以前版本写在这里,高级版本可以直接写public或全局下
无返回值,需要声明也需要实现
可以有参数,可以发生重载
*/
// 声明一个吃饭函数
void eat();
};
#endif // STUDENT_H
// 文件student.cpp中内容
#include "student.h"
#include<QDebug>
Student::Student(QObject *parent) : QObject(parent)
{
}
// 实现吃饭函数
void Student::eat(){
qDebug()<<"干饭人,干饭魂";
}
- 创建老师和学生对象,并建立联系
- emit 调用信号函数
// 文件MainWindow.cpp内容
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// 创建老师和学生的对象
Teacher * hdh = new Teacher(this);
Student * zhangsan = new Student(this);
// 创建信号连接
connect(hdh,&Teacher::class_over,zhangsan,&Student::eat);
// 老师发出信号
emit hdh->class_over();
/*
当信号和槽发生重载时,需要用函数指针来明确指向函数的地址
语法:void (作用域:: * 指针变量名)(参数类型) = &函数;
void (Teacher:: * teacher_signal)() = &Teacher::class_over;
void (Student:: * student_slots)() = &Student::eat;
connect(hdh,teacher_signal,zhangsan,student_slots);
emit hdh->class_over();
*/
MainWindow:~MainWindow()
{
}
拓展:
- 信号是可以连接其他信号
- 一个信号可以连接多个槽函数
- 多个信号可以连接同一个槽函数
- 信号和槽函数的参数必须一一对应
- 信号的参数个数 >= 槽函数参数个数,但剩下的类型也要一一对应
- 信号和槽连接后可以使用disconnect断开
Qt4版本信号槽写法
connect(hdh,SIGNAL(class_over()),zhangsan,SLOTS(eat()));
在SIGNAL和SLOTS中直接传入信号和槽函数,以及对应的参数。优点是参数直观,但缺点是SIGNAL和SLOTS在运行时是将信号和槽转换成了字符串,不会去检测参数类型顺序正确与否,难发现错误。
信号和槽连接后可以使用disconnect断开
Qt4版本信号槽写法
connect(hdh,SIGNAL(class_over()),zhangsan,SLOTS(eat()));
在SIGNAL和SLOTS中直接传入信号和槽函数,以及对应的参数。优点是参数直观,但缺点是SIGNAL和SLOTS在运行时是将信号和槽转换成了字符串,不会去检测参数类型顺序正确与否,难发现错误。