QT学习---day2---信号和槽函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/XUCHEN1230/article/details/84928781

qt中的信号和槽:(重点)
//需求:点击按钮,关闭窗口;
4个主要内容:
connect(信号的发送者【按钮】,发送的信号【点击的信号】,信号的接受者,处理的函数【槽函数】)
处理的过程:按钮发送一个“点击”的信号,窗口接受一个“点击”的信号,将信号传递给“槽函数”。
//4 signals inherited from QAbstractButton,connect中的信号查找。
示例如下:
    //需求:点击btn 关闭窗口
    //参数1 信号的发送者  参数2 发送的信号(信号地址)   参数3  信号的接受者   参数4 处理的槽函数(槽函数的地址)
    //槽函数:public slot
     connect(btn,&QPushButton::clicked,this,&myWidget::close);
优点:松散耦合。左右事件本来不是相关的,利用connect关联起来,将信号发送和信号接收连接起来。
//****************************************************************************************


//****************************************************************************************
第二个项目:
自定义的信号和槽
    qt的自定义信号:
        返回值 void
        需要声明,不需要实现
        可以有参数
    自定义槽函数:
        返回值void
        需要声明,需要实现
        可以有参数
    触发自定义的信号
        emit

//teacher.h
#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

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

signals:
    //自定义的信号需要写到signal下:
    //返回的类型必须是void,
    //信号只需要声明,不需要实现,
    //信号可以有参数,可以重载;
    void hungry();

public slots:
    //自定槽函数的地方;
    //高版本可以写到public下,或者写成全局函数;(个人感觉写到这里更规范)。
};

#endif // TEACHER_H
//stude.h
#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

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

signals:

public slots:
    //自定槽函数的地方;
    //高版本可以写到public下,或者写成全局函数;(个人感觉写到这里更规范)。
    //槽函数需要声明也需要实现;
    //槽函数也可以有函数,也可以重载;
    void treat();
};

#endif // STUDENT_H
//mywidget2.h
#ifndef MYWIDGET2_H
#define MYWIDGET2_H

#include <QWidget>
#include "teacher.h"
#include "student.h"

class mywidget2 : public QWidget
{
    Q_OBJECT

public:
    mywidget2(QWidget *parent = 0);
    ~mywidget2();

    //声明两个对象:
    //成员属性可以保存它;
    Teacher * zt;
    student * st;

    void classOver();
};

#endif // MYWIDGET2_H
//teacher.cpp
#include "teacher.h"

Teacher::Teacher(QObject *parent) : QObject(parent)
{

}

//student.cpp
#include "student.h"
#include <QDebug>
student::student(QObject *parent) : QObject(parent)
{

}

void student:: treat()
{
    qDebug()<<"请老师吃饭";

}

//mywidget2.cpp
#include "mywidget2.h"

//***************************************************************************************************************************************************

项目实践:

//需求:创建两个类:teacher 类 ,student 类
//下课后,老师teacher zt  会发出一个信号---饿了  (发出信号)----自定义信号
//学生响应信号student st  处理 信号的槽函数,请客吃饭;

//mywidget2.cpp
#include "mywidget2.h"


//需求:创建两个类:teacher 类 ,student 类
//下课后,老师teacher zt  会发出一个信号---饿了  (发出信号)----自定义信号
//学生响应信号student st  处理 信号的槽函数,请客吃饭;

mywidget2::mywidget2(QWidget *parent)
    : QWidget(parent)
{
    zt = new Teacher(this);//将老师对象扔到childre表里去了;
    st = new student(this);//




    //连接老师和学生:
    connect(zt,&Teacher::hungry,st,&student::treat);
    //需要时机触发:
    classOver();
}

void mywidget2::classOver()
{
    //触发老师饿了的信号
    //老师饿了的信号属于自定义信号,触发自定义信号的关键字 emit
    emit zt->hungry();
}



mywidget2::~mywidget2()
{

}
//main.cpp
#include "mywidget2.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    mywidget2 w;
    w.show();

    return a.exec();
}

//只用在源文件mywidget2.cpp中更改即可

//********************************************************************************************
当自定义信号和自定义槽函数发生重载时解决方法:
用函数指针明确调用的是有参还是无参的函数;
比如:将上述无参的自定义信号和自定义槽改为有参的情况,则:

//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:
    //自定槽函数的地方;
    //高版本可以写到public下,或者写成全局函数;(个人感觉写到这里更规范)。
    //槽函数需要声明也需要实现;
    //槽函数也可以有函数,也可以重载;
    void treat();
    void treat(QString foodname);
};

#endif // STUDENT_H
//teacher .h
#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

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

signals:
    //自定义的信号需要写到signal下:
    //返回的类型必须是void,
    //信号只需要声明,不需要实现,
    //信号可以有参数,可以重载;
    void hungry();

    void hungry(QString foodname);//信号有参的情况

public slots:
    //自定槽函数的地方;
    //高版本可以写到public下,或者写成全局函数;(个人感觉写到这里更规范)。
};

#endif // TEACHER_H
//mywidget2.h
#define MYWIDGET2_H

#include <QWidget>
#include "teacher.h"
#include "student.h"

class mywidget2 : public QWidget
{
    Q_OBJECT

public:
    mywidget2(QWidget *parent = 0);
    ~mywidget2();

    //声明两个对象:
    //成员属性可以保存它;
    Teacher * zt;
    student * st;

    void classOver();
};

#endif // MYWIDGET2_H
//student.cpp
#include "student.h"
#include <QDebug>
student::student(QObject *parent) : QObject(parent)
{

}

void student:: treat()
{
    qDebug()<<"请老师吃饭";

}

//槽函数有参的情况
void student::treat(QString foodname){

     qDebug()<<"请老师吃饭,老师要吃:"<<foodname;
}
//teacher.cpp
#include "teacher.h"

Teacher::Teacher(QObject *parent) : QObject(parent)
{

}
//mywidget2.cpp
#include "mywidget2.h"


//需求:创建两个类:teacher 类 ,student 类
//下课后,老师teacher zt  会发出一个信号---饿了  (发出信号)----自定义信号
//学生响应信号student st  处理 信号的槽函数,请客吃饭;

mywidget2::mywidget2(QWidget *parent)
    : QWidget(parent)
{
    zt = new Teacher(this);//将老师对象扔到childre表里去了;
    st = new student(this);//




    //连接老师和学生:
    //connect(zt,&Teacher::hungry,st,&student::treat);

    //有参情况的连接:
    //函数指针指向函数地址;
    void (Teacher:: *teachersignal)(QString) = &Teacher::hungry;
    void (student::*studentslot)(QString) = &student::treat;//这两句话是关键

    connect(zt,teachersignal,st,studentslot);

    //需要时机触发:
    classOver();
}

void mywidget2::classOver()
{
    //触发老师饿了的信号
    //老师饿了的信号属于自定义信号,触发自定义信号的关键字 emit

    emit zt->hungry();//触发无参信号

    emit zt->hungry("热干面");//触发有参信号
}



mywidget2::~mywidget2()
{

}

//上述调用Connect时,有参函数的地址需要定义一个函数指针指向函数的地址,可以解决自定义信号和自定义槽函数的重载问题;
//在调用emit触发槽函数时,也要明确是调用的有参还是无参;

另附:
//QString 转 char*
qDebug()<<"请老师吃饭,老师要吃:"<<foodname.toUtf8().data();
//1.先转成Qbytearry类型、
//2.再转为char*

//******************************
归纳:
当自定义信号和槽 出现重载时候,原先写法失效,因为执行的函数地址不明确;
解决方法:利用函数指针,来明确指向哪个函数的地址
QString 转char*   toUtf8() 转为 QBtyeArry类型,再利用data转成char*;
//系统自带的函数可能也会发生重载,此时也用上述方法进行解决。

//********************************************************************************************************
信号和槽的扩展:
//用按钮触发信号1,信号1连接信号2
//信号2触发槽函数;

//断开信号和槽:
disconnect();

扫描二维码关注公众号,回复: 4476550 查看本文章

//扩展:
//1.信号可以连接信号;
//2.信号和槽可以断开 disconnect
//3.一个信号可以触发多个槽函数;
//4.多个信号可以连接同一个槽函数;
//5.信号和槽的参数必须一一对应吗?不一定
    //信号的参数个数必须多余槽函数的参数,但是类型必须一一对应。
    

参考:黑马程序员培训视频

猜你喜欢

转载自blog.csdn.net/XUCHEN1230/article/details/84928781