1.重载自定义信号与槽:
定义天黑类:里面有一个有参数的信号和没有参数的信号
tianhei.h
#ifndef TIANHEI_H #define TIANHEI_H #include <QObject> class Tianhei : public QObject { Q_OBJECT public: Tianhei(); //构造函数声明 signals: void tianhei(); void tianhei(QString name); //信号只需声明 public slots: }; #endif // TIANHEI_H
定义想你类:同样一个有参数一个没有参数
xingni.h
#ifndef XINGNI_H #define XINGNI_H #include <QObject> class Xingni : public QObject { Q_OBJECT public: explicit Xingni(QObject *parent = nullptr); signals: public slots: void xiangni(); void xiangni(QString name); //槽函数 }; #endif // XINGNI_H
xingni.c
#include "xingni.h" #include <QDebug> Xingni::Xingni(QObject *parent) : QObject(parent) { } void Xingni::xiangni(){ qDebug()<<"想你了"; } void Xingni::xiangni(QString name){ qDebug()<<"想你了"<<name; }
我们选择第一种按键绑定方式,即用中转函数,
点击按钮,按钮发送点击信号,MainWindow接收信号,执行heilai()函数;
heilai()函数会让hei发送tianhei信号,xing接收信号执行xingni槽函数;
但是我们发现,由于信号函数和槽函数存在两个重名的函数,一个有参数,一个没有参数,程序存在歧义,不知道执行哪一个,这时候就是指针大显身手的时候了。我们定义一个函数体指针分别接收有参数的信号函数和槽函数,把两个指针传到connect中去就好了;
mainwindow.c
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> #include <QPushButton> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); this->setWindowTitle("love"); //设置固定大小,设置完成不可拉伸 this->setFixedSize(400,300); QPushButton *butten=new QPushButton("点我天黑",this); butten->move(150,100); //定义一个按钮实例子 this->hei =new Tianhei(); //实例化对象,注意后面括号 this->xing =new Xingni(); void (Xingni::*XINGNI)(QString)=&Xingni::xiangni; void (Tianhei::*TIANHEI)(QString)=&Tianhei::tianhei; // connect(butten,&QPushButton::clicked,hei,XINGNI); connect(butten,&QPushButton::clicked,this,&MainWindow::heilai); connect(hei,TIANHEI,xing,XINGNI); //天黑发出天黑信号,xing接收,调用槽函数; } void MainWindow::heilai(){ qDebug()<<"天要黑了!"; emit hei->tianhei("刘亦菲"); //定义的有参数所以要传参 } MainWindow::~MainWindow() { delete ui; }
void (Xingni::*XINGNI)(QString)=&Xingni::xiangni; void (Tianhei::*TIANHEI)(QString)=&Tianhei::tianhei;
void是函数返回值,(Xingni::*XINGNI)(QString)=&Xingni::xiangni;XINGNI中是Xingni::xiangni的地址,由于前边有参数,因此会自动传有参数的函数地址。QString----->QByteArray-------->char * 去引号
qDebug()<<"想你了"<<name.toUtf8().data();
2.信号与槽总结
(1)发送者与接收者是需要是QObjec的子类(槽函数是全局,lambda除外)
(2)信号与槽返回值都是void类型。
(3)信号只需要声明不需要定义实现,槽函数需要声明也需要实现(注意继承方式,public,private,protected)。
(4)槽函数是普通函数,会受到public,private,protected影响。
(5)使用emit在恰当的位置发送信号
(6)任何成员函数,static函数,全局函数和Lambda表达式都可以作为槽函数
(7)使用connect()函数连接信号与槽
(8)信号与槽的参数要一致,参数类型一致,槽函数参数可以比信号少,但是顺序要一直。
举例:
signal(Qstring)和slot(Qstring)
signal(Qstring,Qstring)和slot(Qstring)
signal(Qstring,Qstring)和slot(Qstring,int)错误
signal(Qstring,Qstring,int)和slot(Qstring,Qstring)
signal(Qstring,Qstring,int)和slot(Qstring,int) 错误
(9)信号与槽可以一对一,一对多(发出信号,槽函数一个一个执行,顺序不确定)多对一(发出意一个信号,槽函数都执行)
(10)信号可以连接信号
(11)槽可以断开连接(disconnect),槽可以被取消连接(当一个对象delete了,取消这个连接)
(12)可以使用C++11中的lambda