信号与槽(Signal & Slot)是 Qt 编程的基础,也是 Qt 的一大创新。因为有了信号与槽的编程机制,在 Qt 中处理界面各个组件的交互操作时变得更加直观和简单。
信号(Signal)就是在特定情况下被发射的事件,例如 PushButton 最常见的信号就是鼠标单击时发射的 clicked() 信号,一个 ComboBox 最常见的信号是选择的列表项变化时发射的CurrentIndexChanged() 信号。
GUI 程序设计的主要内容就是对界面上各组件的信号的响应,只需要知道什么情况下发射哪些信号,合理地去响应和处理这些信号就可以了。
槽(Slot)就是对信号响应的函数。槽就是一个函数,与一般的 C++函数是一样的,可以定义在类的任何部分(public、private 或 protected),可以具有任何参数,也可以被直接调用。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。
信号与槽关联是用 QObject::connect() 函数实现的:
connect(btn,&QPushButton::clicked,this,&QWidget::close);
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 第一个按钮
QPushButton * btn=new QPushButton;
//show以顶层方式弹出窗口坤健
// btn->show();
//让队形依赖于widget窗口
btn->setParent(this);
//显示文本
btn->setText("关闭按钮");
// 创建第二个按钮,按照按钮的大小创建窗口
QPushButton * btn2=new QPushButton("第二个按钮",this);
btn2->move(100,100);
// 重置窗口大小
resize(600,400);
// 设置固定窗口大小
setFixedSize(600,400);
// 设置窗口标题
setWindowTitle("第一个窗口");
//需求,点击关闭按钮,关闭窗口
//参数1:信号发送者 参数2:发送的信号 参数3:信号接受者 参数4:处理的槽函数
connect(btn,&QPushButton::clicked,this,&QWidget::close);
}
//Teacher类 老师类
//Student类 学生类
//下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭
依次创建teacher和student类
teacher.h
#ifndef TEACHER_H
#define TEACHER_H
#include
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
//自定义信号,写在signals下
//返回值是void,只需申明,
//可以有参数,可以重载
void hungry();
};
#endif // TEACHER_H
teacher.cpp
#include "teacher.h"
Teacher::Teacher(QObject *parent)
: QObject{parent}
{
}
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
//早期Qt版本,必须要写到public slots,高级本本可以写到public或者全局下
//返回值void,需要申明,也需要实现
//可以有参数,可以发生重载
void treat();
signals:
};
#endif // STUDENT_H
student.cpp
#include "student.h"
#include
Student::Student(QObject *parent)
: QObject{parent}
{
}
void Student::treat(){
qDebug()<<"请老师吃饭";
}
widget.h
#include "widget.h"
#include "ui_widget.h"
//Teacher类 老师类
//Student类 学生类
//下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//创建一个老师对象
this->th=new Teacher(this);
//创建一个学生对象
this->st=new Student(this);
//老师饿了,学生请客的连接
connect(th,&Teacher::hungry,st,&Student::treat);
//调用下课函数,触发信号
classIsOver();
}
void Widget::classIsOver(){
//下课函数,调用后,触发老师饿了的信号
emit th->hungry();
}
Widget::~Widget()
{
delete ui;
}
teach.h
#ifndef TEACHER_H
#define TEACHER_H
#include
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
//自定义信号,写在signals下
//返回值是void,只需申明,
//可以有参数,可以重载
void hungry();
void hungry(QString foodName);
};
#endif // TEACHER_H
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
//早期Qt版本,必须要写到public slots,高级本本可以写到public或者全局下
//返回值void,需要申明,也需要实现
//可以有参数,可以发生重载
void treat();
void treat(QString foodName);
signals:
};
#endif // STUDENT_H
student.cpp
#include "student.h"
#include
Student::Student(QObject *parent)
: QObject{parent}
{
}
void Student::treat(){
qDebug()<<"请老师吃饭";
}
void Student::treat(QString foodName){
//QString转换为char *
qDebug()<<"请老师吃饭,老师要吃"<
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include
//Teacher类 老师类
//Student类 学生类
//下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//创建一个老师对象
this->th=new Teacher(this);
//创建一个学生对象
this->st=new Student(this);
//老师饿了,学生请客的连接
// connect(th,&Teacher::hungry,st,&Student::treat);
//调用下课函数,触发信号
// classIsOver();
//连接带参数的信号和槽
//指针->地址
//函数指针->函数地址
void(Teacher ::*teacherSignal)(QString)=&Teacher::hungry;
void(Student::*studentSlot)(QString)=&Student::treat;
connect(th,teacherSignal,st,studentSlot);
// classIsOver();
//点击一个下课按钮,触发下课
QPushButton * btn=new QPushButton("下课",this);
//重置窗口大小
this->resize(600,400);
//点击按钮,触发下课
// connect(btn,&QPushButton::clicked,this,&Widget::classIsOver);
void(Teacher ::*teacherSignal2)(void)=&Teacher::hungry;
void(Student::*studentSlot2)(void)=&Student::treat;
connect(th,teacherSignal2,st,studentSlot2);
//信号连接信号
connect(btn,&QPushButton::clicked,th,teacherSignal2);
//断开信号
disconnect(th,teacherSignal2,st,studentSlot2);
//扩展
//1、信号是可以连接信号;
//2、一个信号可以连接多个槽函数;
//3、多个信号可以连接同一个槽函数;
//4、信号和槽函数的参数,必须类型一一对应;
//5、信号的参数个数可以多余槽函数的参数个数。
//Qt4版本以前的信号和槽连接方式
//利用Qt4信号和槽,连接无参版本
connect(th,SIGNAL(hungry()),st,SLOT(treat()));
//优点参数直观,缺点类型不做检测L
}
void Widget::classIsOver(){
//下课函数,调用后,触发老师饿了的信号
emit th->hungry();
emit th->hungry("宫保鸡丁");
}
Widget::~Widget()
{
delete ui;
}
1、信号是可以连接信号;
2、一个信号可以连接多个槽函数;
3、多个信号可以连接同一个槽函数;
4、信号和槽函数的参数,必须类型一一对应;
5、信号的参数个数可以多余槽函数的参数个数。