信号和槽——Qt

什么是信号和槽

什么是信号?什么是槽?

  • 信号的发送者发送的是具体的信号,信号的接收者,对信号的处理(槽函数)

  • 信号槽的优点:松散耦合,信号发送端和接收端本身是没有关联的,通过concent连接,将两端耦合在一起。

  • 连接函数 :connect(参数1,参数2,参数3,参数4)

  • 参数

    • 参数1 信号的发送者
    • 参数2 发送的信号(函数地址)
    • 参数3 信号的接受者
    • 参数4 处理的槽函数 (函数的地址)
  • 松散耦合
    实现 点击按钮 关闭窗口的案例
    connect(btn , &QPushButton::click , this , &QWidget::close );

//创建一个自己的按钮对象
    MyPushButton * myBtn = new MyPushButton;
    myBtn->setText("我自己的按钮");

    myBtn->move(200,0);
    myBtn->setParent(this); //设置到对象树中


    //需求  点击我的按钮 关闭窗口
    //参数1:信号的发送者 参数2:发送的信号(函数的地址) 参数3:信号的接受者 参数4:处理的槽函数
    //connect( myBtn, &MyPushButton::clicked, this, &myWidget::close  );
    connect( myBtn, &QPushButton::clicked, this, &QWidget::close  );

运行结果:当摁完我自己的按钮的图标后,主窗口就会自动关闭,相当于摁了×
在这里插入图片描述


自定义信号和槽

无参数的信号和槽

这是一个自定义类的头文件:

#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

class teacher : public QObject
{
    Q_OBJECT
public:
    explicit teacher(QObject *parent = nullptr);

signals:

};

#endif // TEACHER_H
  • 自定义信号 写到signals:下
  • 返回值是void信号只需要声明,不需要实现
  • 可以有参数,可以重载

1. 信号的声明

这是在teacher类头文件中的信号声明

#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = 0);
signals:
    //自定义信号  写到signals下
    //返回值是void ,只需要声明,不需要实现
    //可以有参数,可以重载
    
    //这是一个无参的信号
    void hungry();
    
    //一个有参的信号
    void hungry(QString foodName);

public slots:
};
#endif // TEACHER_H

由于信号只需要声明不需要实现,所以不需要在主函数中对声明的这个void hungry();有具体的实现。

槽函数进行声明

  • 早期Qt版本 必须要写到public slots,高级版本可以写到public或者全局下
  • 返回值 void ,需要声明,也需要实现
  • 可以有参数,可以重载

2. 槽函数的声明

在student的头文件中,对槽函数进行声明

#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>
class student : public QObject
{
    Q_OBJECT
public:
    explicit student(QObject *parent = nullptr);
    
    // 声明一个槽函数
    void treat();

signals:
};
#endif // STUDENT_H

3. 槽函数的实现

在 Student的源文件中对槽函数进行声明和实现

#include "student.h"

//添加要输出信息的头文件。
#include<QDebug>

student::student(QObject *parent) : QObject(parent)
{
}
void  student::treat()
{
    qDebug() << "去买饭";
}

4. 信号和槽的连接

  1. wideget头文件中,声明两个指针和一个函数触发信号, 并在源文件中实现他们,然后实现信号和槽函数的连接
private:
    Ui::Widget *ui;

    // 自己声明两个默认的指针
    teacher * zt;
    student * st;

    //声明一个函数触发信号,在源文件中实现这个函数。
    void classover();
  1. 源文件中实现,并建立信号与槽函数的连接。
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 创建一个老师的对象
    this->zt = new teacher(this);

    // 创建一个学生的对象。
    this->st = new student(this);

    //将信号与槽函数进行连接。
    connect(zt,&teacher::hungry, st,&student::treat);

    //先建立连接,再调用启动信号的函数
    classover();

}

void Widget::classover()
{
    // 下课函数,调用后触发hungry的信号
    //自定义信号输出发时有一个关键字emit
    emit zt->hungry();

}

有参数的信号和槽

1. 有参信号的声明

  1. 带参数的信号声明
    信号无需实现也无需声明
signals:
   
    // 无参数的信号,无需实现也无需胜利。
    void hungry() ;
    
    // 参数的信号,无需实现也无需声明。
    void hungry(QString foodname);

2. 有参槽函数的声明

在头文件中对槽函数的定义

public:
    explicit student(QObject *parent = nullptr);

    // 声明一个槽函数
    void treat();
    
    // 有参数的槽函数
    void treat(QString foodname);
    

3. 有参槽函数的实现

#include "student.h"

//添加要输出信息的头文件。
#include<QDebug>

student::student(QObject *parent) : QObject(parent)
{

}
// 无参槽函数的实现
void  student::treat()
{
    qDebug() << "去买饭";
}

// 有参槽函数的实现
void student::treat(QString foodname)
{
    qDebug() << "去买饭,要吃:" << foodname ;
}

4. 信号与槽的连接

  1. 在 widget头文件中,定义两个指针和一个实现触发信号的函数,并在原文件中实现他们
private:
    Ui::Widget *ui;

    // 自己声明两个默认的指针
    teacher * zt;
    student * st;

    //声明一个函数触发信号,在源文件中实现这个函数。
    void classover();
  1. 在源文件中实现指针的声明,信号与槽函数的连接
    // 创建一个老师的对象
    this->zt = new teacher(this);

    // 创建一个学生的对象。
    this->st = new student(this);

    // 连接带参数的信号和槽
    // 指针 -> 地址
    // 函数指针 -> 函数地址
    void (teacher::*teachersignal)(QString) = &teacher::hungry ;
    void (student::*studentsolt)(QString) = &student::treat;
    connect(zt,teachersignal, st,studentsolt);
    // 触发信号
    classover();

// 触发函数
void Widget::classover()
{
    // 下课函数,调用后触发hungry的信号
    //自定义信号输出发时有一个关键字emit
    //emit zt->hungry();
    emit zt->hungry("煎饼卷大葱");
}

输出结果:
在这里插入图片描述会发现输出结果中有双引号。如果要去掉双引号的话,需要将QString转成char*

// 有参考函数的实现
void student::treat(QString foodname)
{
    // 将QString转成char*:用tuutf8是先转成QByteArray,再转char*
    qDebug() << "去买饭,要吃:" << foodname.toUtf8().data();
}

输出结果:
在这里插入图片描述

按钮触发信号连接槽

通过一个信号来触发另一个信号,创建一个下课的按钮,通过这个按钮来触发下课信号函数。

    // 创建一个老师的对象
    this->zt = new teacher(this);

    // 创建一个学生的对象。
    this->st = new student(this);

    // 连接带参数的信号和槽
    // 指针 -> 地址
    // 函数指针 -> 函数地址
    void (teacher::*teachersignal)(QString) = &teacher::hungry ;
    void (student::*studentsolt)(QString) = &student::treat;
    connect(zt,teachersignal, st,studentsolt);
    classover();	

		//创建一个下课按钮
    QPushButton *bth =new QPushButton("下课",this);
    //设置窗口大小
    this->resize(600,400);

    //点击按钮,触发下课。
    connect(bth,&QPushButton::clicked,this,&Widget::classover);

在这里插入图片描述
点完下课按钮后。
在这里插入图片描述

链接过程
在这里插入图片描述

信号链接信号

    // 创建一个老师的对象
    this->zt = new teacher(this);

    // 创建一个学生的对象。
    this->st = new student(this);
    
    //创建一个下课按钮
    QPushButton *bth =new QPushButton("下课",this);
    //设置窗口大小
    this->resize(600,400);

    // 无参信号连接槽
    void (teacher::*teachersignal2)(void) = &teacher::hungry ;
    void (student::*studentsolt2)(void) = &student::treat;
    connect(zt,teachersignal2, st,studentsolt2);

    // 信号链接信号
    connect(bth,&QPushButton::clicked,zt,teachersignal2);

在这里插入图片描述

连接的断开

关键字:disconnect
断开连接的参数和建立连接的参数是相同的,想断开哪个连接,直接传递建立连接的参数。

		// 信号链接信号
    connect(bth,&QPushButton::clicked,zt,teachersignal2);
    // 断开上面的连接
    disconnect(bth,&QPushButton::clicked,zt,teachersignal2);

拓展

1. 信号是可以连接信号
2. 一个信号可以连接多个槽函数
3. 多个信号 可以连接 同一个槽函数
4. 信号和槽函数的参数 必须类型一一对应
5. 信号和槽的参数个数  是不是要一致?信号的参数个数 可以多余槽函数的参数个数
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值