Qt信号和槽

简介: Qt信号和槽

一、定义

信号与槽(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类

 1、自定义信号

teacher.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 hungry();
};
 
#endif // TEACHER_H

teacher.cpp

 
#include "teacher.h"
 
Teacher::Teacher(QObject *parent)
    : QObject{parent}
{
 
}
 


2、自定义槽

student.h

 
#ifndef STUDENT_H
#define STUDENT_H
 
 
#include <QObject>
 
 
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<QDebug>
Student::Student(QObject *parent)
    : QObject{parent}
{
 
}
void Student::treat(){
    qDebug()<<"请老师吃饭";
}


3、关联信号和槽并发送信息

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 <QObject>
 
 
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 <QObject>
 
 
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<QDebug>
Student::Student(QObject *parent)
    : QObject{parent}
{
 
}
void Student::treat(){
    qDebug()<<"请老师吃饭";
}
 
void Student::treat(QString foodName){
    //QString转换为char *
    qDebug()<<"请老师吃饭,老师要吃"<<foodName.toUtf8().data();
}

widget.cpp

 
#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>
 
//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、信号的参数个数可以多余槽函数的参数个数。

使用lamdba

 
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()));
    //优点参数直观,缺点类型不做检测
 
    //lambda
    //值传递
    [=](){
        btn->setText("AAA");
    }();
    //引用传递
    [&](){
        btn->setText("BBB");
    }();
 
    int ret=[]()->int{return 1000;}();
    qDebug()<<"ret="<<ret;
 
    //利用lambda表达式,实现点击按钮,关闭窗口
    QPushButton *btn2=new QPushButton;
    btn2->setText("关闭");
    btn2->move(100,0);
    btn2->setParent(this);
    connect(btn2,&QPushButton::clicked,this,[=](){
        emit th->hungry("lalala");
    });
}
目录
相关文章
|
1月前
|
存储 安全 编译器
【Qt 底层机制之信号和槽 】深入探究Qt信号和槽背后的原理
【Qt 底层机制之信号和槽 】深入探究Qt信号和槽背后的原理
432 4
|
1月前
【Qt 学习笔记】按钮实现helloworld | 信号与槽概述
【Qt 学习笔记】按钮实现helloworld | 信号与槽概述
47 0
|
1月前
|
编译器 C++ 开发者
QT基础【7-跨进程发送信号】
QT基础【7-跨进程发送信号】
|
1月前
|
开发者
QT基础【6-跨界面发送信号】
QT基础【6-跨界面发送信号】
|
1月前
QT自定义信号,信号emit,信号参数注册
使用signals声明返回值是void在需要发送信号的地方使用emit 信号名字(参数)进行发送在需要链接的地方使用connect进行链接ct进行链接。
27 0
QT自定义信号,信号emit,信号参数注册
|
1月前
|
存储 API C++
【Qt 信号槽】深入探索 Qt 信号和槽机制中的引用传递“ (“A Deep Dive into Reference Passing in Qt Signal and Slot Mechanism“)
【Qt 信号槽】深入探索 Qt 信号和槽机制中的引用传递“ (“A Deep Dive into Reference Passing in Qt Signal and Slot Mechanism“)
151 0
|
1月前
|
安全 编译器 开发者
【Qt 学习笔记】Qt信号和槽的其他说明及Lambda表达式
【Qt 学习笔记】Qt信号和槽的其他说明及Lambda表达式
68 0
|
27天前
|
安全 C++ Windows
Qt信号与槽机制
Qt信号与槽机制
19 1
|
1月前
|
图形学 C++ 容器
QT信号与槽机制 和 常用控件介绍
QT信号与槽机制 和 常用控件介绍
QT信号与槽机制 和 常用控件介绍