zl程序教程

您现在的位置是:首页 >  工具

当前栏目

Qt自定义信号和槽

Qt 自定义 信号
2023-09-14 09:13:38 时间

案例需求: 创建一个老师类和学生类,下课后,老师触发饿了的信号,学生响应老师饿了的信号,并且请老师吃饭
老师类
.h

#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr);
  //自定义信号,写到signal下
signals:
     //返回值是void
    //只需要声明,不需要实现
    //可以有参数,可以发生重载
    void hungry();
};

#endif // TEACHER_H

.cpp

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

学生类
.cpp

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

}
//学生的槽函数
 void Student::treat()
 {
     qDebug()<<"请老师吃饭"<<endl;
 }

.h

#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);
    //返回值是void
    //需要有声明,需要有实现
    //可以有参数,可以发生重载
    void treat();
signals:

};

#endif // STUDENT_H

这里注意槽函数的版本区别:
在这里插入图片描述
widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include"student.h"
#include"teacher.h"
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    Student* st;
    Teacher* tt;

    void classisover();
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    st=new Student(this);
    tt=new Teacher(this);
    //连接信号和槽
    connect(tt,&Teacher::hungry,st,&Student::treat);
    //调用该函数,这样信号和槽连接后,调用该函数后才能触发信号
    classisover();
}
void Widget::classisover()
{
    //触发老师饿了的信号
    emit tt->hungry();
}
Widget::~Widget()
{
}

在这里插入图片描述
上面为什么连接信号和槽后,还要再写一个classisover函数来触发信号呢?
因为连接信号和槽是为了确保在信号被触发的时候,槽函数能够执行来处理事件,而这里我们这是连接了老师的信号和学生的槽函数,还需要触发老师饿了的信号,即调用老师的hungry函数

自定义信号和槽重载发生的问题及解决措施

在这里插入图片描述

在这里插入图片描述

上面两张图片可知,我们重载了有参的信号和槽,此时我们再连接信号和槽:因为有参信号和槽连接和无参信号和槽连接写法一致,系统无法区分,就会报错
在这里插入图片描述
解决方法:利用函数指针指向函数地址
widget.cpp

#include "widget.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    st=new Student(this);
    tt=new Teacher(this);
    //连接信号和槽
    //connect(tt,&Teacher::hungry,st,&Student::treat);
    
    //连接有参的信号和槽
    //函数指针可以指向函数地址
    //这里槽函数和信号函数取地址都要加&
    //因为这里是在当前Widget的构造函数里面调用Teacher类和Student类里面的函数,所以要加类名作用域
    void(Teacher::*ttSignal)(QString)=&Teacher::hungry;
    void(Student::*stSlot)(QString)=&Student::treat;
    //将原来的函数地址替换成函数指针
    connect(tt,ttSignal,st,stSlot);
    //调用该函数,这样信号和槽连接后,调用该函数后才能触发信号
    classisover();
}
void Widget::classisover()
{
    //触发老师饿了的信号
    //emit tt->hungry();
    
    //触发老师饿了的有参信号
    emit tt->hungry("火锅,烧烤,麻辣烫!!!");
}
Widget::~Widget()
{
}

在这里插入图片描述

解决输出字符串加上双引号的问题?

在这里插入图片描述

 //学生槽函数的重载版本
 void  Student::treat(QString foodName)
 {
     //QString 转char*就可以解决双引号问题
     //转char*方法:
     //先通过.toUtf8变为QByteArray类型,再通过.data()变为char*
     qDebug()<<"请老师吃"<<foodName.toUtf8().data()<<endl;
 }

在这里插入图片描述

总结:当信号和槽发生重载的时候,需要通过函数指针明确指出函数地址

信号连接信号

#include "widget.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    st=new Student(this);
    tt=new Teacher(this);
    //创建自己的按钮控件
    QPushButton* mybtn=new QPushButton("下课",this);
    resize(600,400);
    
    void(Teacher::*ttSignal)()=&Teacher::hungry;
    void(Student::*stSlot)()=&Student::treat;
    //信号和槽连接
    connect(tt,ttSignal,st,stSlot);
    //信号是可以连接信号的
    connect(mybtn,&QPushButton::clicked,tt,ttSignal);
    //当老师饿了的信号由按钮点击来触发以后,就不需要专门的函数来调用老师饿了的函数,来触发饿了信号,因此下面这个下课函数可以不写
    //classisover();
}
void Widget::classisover()
{
    emit tt->hungry("火锅,烧烤,麻辣烫!!!");
}
Widget::~Widget()
{
}

在这里插入图片描述

在这里插入图片描述

可以断开信号和槽的连接

    st=new Student(this);
    tt=new Teacher(this);
    //创建自己的按钮控件
    QPushButton* mybtn=new QPushButton("下课",this);
    resize(600,400);
    void(Teacher::*ttSignal)()=&Teacher::hungry;
    void(Student::*stSlot)()=&Student::treat;
    //信号和槽连接
    connect(tt,ttSignal,st,stSlot);
    //信号是可以连接信号的
    connect(mybtn,&QPushButton::clicked,tt,ttSignal);
    //断开信号和槽的连接
    disconnect(tt,ttSignal,st,stSlot);

在这里插入图片描述

一个信号可以响应多个槽函数

可以通过多写几个connect函数,将同一个信号和多个槽函数相连接

多个信号可以连接同一个槽函数

可以通过多写几个connect函数,将同一个槽函数和多个信号相连接

信号和槽函数的参数个数和参数类型必须一一对应

在这里插入图片描述
在这里插入图片描述

信号的参数个数可以多余槽函数参数个数,反之不可以

在这里插入图片描述

Qt4版本的信号和槽的写法

在这里插入图片描述

信号和槽总结

在这里插入图片描述

在这里插入图片描述