QT之信号槽机制基础知识梳理

一、概念

(1)信号:特定情况下被发射的事件;

(2)槽:对信号响应的函数;

二、特点

(1)信号(signals):

         1.1 自定义信号函数,写在signals下;

         1.2 返回值是void,只需要声明,不需要实现;

         1.3 参数可有可无,可以重载;

(2)槽(slots):

         2.1自定义的槽函数,早期的必须写在public slots下,高版本可以写在public下;

         2.2 返回值是void,需要声明也需要实现;

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

         2.3 参数可有可无,可以重载;

         2.4 自定义槽函数形式:

               2.4.1 类的任意成员函数;

               2.4.2 静态函数;

               2.4.3 全局函数;

               2.4.4 Lambda表达式;

(3)触发自定义的信号函数

        3.1 关键字:emit

        3.2 通过类对象调用信号函数      

              eg:      void MyWidget::ClassOver()
                         {
                                emit te->hungry();
                         }

        3.3 调用位置在信号槽机制之后(先实现信号槽的绑定,再调用信号函数)

(4)Q_OBJECT 关键字

         4.1 凡是QObject类(不管是直接子类还是间接子类),都应该在第一行代码写上Q_OBJECT,不能丢失;

         4.2 作用:只有继承了QObject类的类,才具有信号槽的能力;

(5)信号和槽的参数类型必须一致,信号函数的参数个数可以多余槽函数;

(6)QT4版本信号槽连接方式

         例如:connect(bt, SLGNAL(clicked()), this, SLOT(close()));

                   6.1优点:参数直观;

                   6.2缺点:类型不做检测;

三、连接机制

       伪代码:connect(信号的发送者,发送的具体信号(函数的地址),信号的接收者,信号的具体处理(函数的地址));

四、优点

       松散耦合:信号的发送者和信号的接受者本身没有关联,通过connect函数,将两端耦合在一起;

五、案例

(1)利用系统的信号函数和槽函数 (点击按钮关闭窗口)  

//MyWidget.cpp
#include "MyWidget.h"
MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    this->bt = new QPushButton("关闭");

    //按钮布局
    QHBoxLayout *lay = new QHBoxLayout(this);
    lay->addStretch();
    lay->addWidget(bt);
    lay->addStretch();

    //信号槽
    connect(bt, &QPushButton::clicked, this, &MyWidget::close);

    //槽对象也可以用父类(因为子类继承于父类)
    connect(bt, &QPushButton::clicked, this, &Widget::close);
}


//MyWidget.h
#pragma once
#pragma execution_character_set("utf-8")
#include <QtWidgets/QWidget>
#include <QPushButton>
#include <QHBoxLayout>

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    MyWidget(QWidget *parent = Q_NULLPTR);

private:
    QPushButton *bt;
};


//mian.cpp
#include "MyWidget.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyWidget w;
    w.show();
    return a.exec();
}

(2)自定义信号函数和槽函数(下课后,老师触发信号饿了,学生响应请老师吃饭的槽函数)

//Teacher.cpp
#include "Teacher.h"
Teacher::Teacher(QWidget *parent)
	: QWidget(parent)
{
}


//Teacher.h
#pragma once
#pragma execution_character_set("utf-8")
#include <QtWidgets/QWidget>

class Teacher : public QWidget
{
	Q_OBJECT

public:
	Teacher(QWidget *parent = Q_NULLPTR);

private:

signals:
	void hungry();

public slots:
};


//Student.cpp
#include "Student.h"
#include <QDebug>
Student::Student(QWidget *parent)
	: QWidget(parent)
{
}

void Student::treat()
{
	qDebug() << "请老师吃饭!";
}


//Student.h
#pragma once
#pragma execution_character_set("utf-8")
#include <QtWidgets/QWidget>

class Student : public QWidget
{
	Q_OBJECT

public:
	Student(QWidget *parent = Q_NULLPTR);

private:

signals:

public slots:
	void treat();
};


//MyWidget.cpp
#include "MyWidget.h"
MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
	//创建老师对象
	te = new Teacher(this);

	//创建学生对象
	st = new Student(this);

	//信号槽绑定
	connect(te,&Teacher::hungry,st,&Student::treat);

	//调用下课函数
	ClassOver();
}
void MyWidget::ClassOver()
{
	//下课后,老师触发饿了的信号
	emit te->hungry();
}


//MyWidget.h
#pragma once
#pragma execution_character_set("utf-8")
#include <QtWidgets/QWidget>
#include "Teacher.h"
#include "Student.h"

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    MyWidget(QWidget *parent = Q_NULLPTR);

private:
	void ClassOver();
	Teacher *te;
	Student *st;
};


//mian.cpp
#include "MyWidget.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyWidget w;
    w.show();
    return a.exec();
}

(3) 当子定义的信号函数和槽函数出现重载关系

          3.1 需要利用函数指针,明确指出函数的地址

                void (Teacher:: *teacherSignal)(QString) = &Teacher::hungry;

          3.2 QString 转换 char*

               foodName.toUtf8().data();          

//Teacher.cpp
#include "Teacher.h"
Teacher::Teacher(QWidget *parent)
	: QWidget(parent)
{
}


//Teacher.h
#pragma once
#pragma execution_character_set("utf-8")
#include <QtWidgets/QWidget>

class Teacher : public QWidget
{
	Q_OBJECT

public:
	Teacher(QWidget *parent = Q_NULLPTR);

private:

signals:
	void hungry();
	void hungry(QString foodName);

public slots:
};


//Student.cpp
#include "Student.h"
#include <QDebug>
Student::Student(QWidget *parent)
	: QWidget(parent)
{
}

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

void Student::treat(QString foodName)
{
	qDebug() << "请老师吃饭,老师要吃" << foodName.toUtf8().data();
        //将QString类型转换为char*,作用是取消字符串显示时带双引号。。。
}


//Student.h
#pragma once
#pragma execution_character_set("utf-8")
#include <QtWidgets/QWidget>

class Student : public QWidget
{
	Q_OBJECT

public:
	Student(QWidget *parent = Q_NULLPTR);

private:

signals:

public slots:
	void treat();
	void treat(QString foodName);
};


//MyWidget.cpp
#include "MyWidget.h"
MyWidget::MyWidget(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);

	//创建老师对象
	te = new Teacher(this);

	//创建学生对象
	st = new Student(this);

	//定义函数指针
	void (Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
	void (Student:: *studentSlot)(QString) = &Student::treat;

	//信号槽绑定
	connect(te,teacherSignal,st,studentSlot);

	//调用下课函数
	ClassOver();
}
void MyWidget::ClassOver()
{
	//下课后,老师触发饿了的信号
	/*emit te->hungry();*/
	emit te->hungry("鱼香肉丝");
}


//MyWidget.h
#pragma once
#pragma execution_character_set("utf-8")
#include <QtWidgets/QWidget>
#include "ui_MyWidget.h"
#include "Teacher.h"
#include "Student.h"

class MyWidget : public QWidget
{
	Q_OBJECT

public:
	MyWidget(QWidget *parent = Q_NULLPTR);

private:
	Ui::MyWidgetClass ui;
	void ClassOver();
	Teacher *te;
	Student *st;
};


//main.cpp
#include "MyWidget.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyWidget w;
    w.show();
    return a.exec();
}

(4) 信号1连接信号2,信号2连接槽函数(点击按钮触发限信号,信号去响应槽函数)

          4.1 有参数的情况下

//MyWidget.cpp
#include "MyWidget.h"
#include <QHBoxLayout>
MyWidget::MyWidget(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);

	bt = new QPushButton("下课",this);
	QHBoxLayout *ly = new QHBoxLayout(this);

	ly->addStretch();
	ly->addWidget(bt);
	ly->addStretch();

	//创建老师对象
	te = new Teacher(this);

	//创建学生对象
	st = new Student(this);

	//定义函数指针
	void (Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
	void (Student:: *studentSlot)(QString) = &Student::treat;

	//信号槽绑定
	connect(bt, &QPushButton::clicked, this, &MyWidget::ClassOver);    //点击按钮,触发信号
	connect(te, teacherSignal, st, studentSlot);                       //信号去触发槽函数
}
void MyWidget::ClassOver()
{
	//下课后,老师触发饿了的信号
	emit te->hungry("鱼香肉丝");
}

//MyWidget.h
#pragma once
#pragma execution_character_set("utf-8")
#include <QtWidgets/QWidget>
#include "ui_MyWidget.h"
#include "Teacher.h"
#include "Student.h"
#include <QPushButton>

class MyWidget : public QWidget
{
	Q_OBJECT

public:
	MyWidget(QWidget *parent = Q_NULLPTR);

private:
	Ui::MyWidgetClass ui;
	void ClassOver();
	Teacher *te;
	Student *st;
	QPushButton *bt;
};

            4.2 没有参数情况下   

                  断开信号槽连接:disconnect();

                  例如:disconnect(te, teacherSignal2, st, studentSlot2); 

//MyWidget.cpp
#include "MyWidget.h"
#include <QHBoxLayout>
MyWidget::MyWidget(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);

	bt = new QPushButton("下课",this);
	QHBoxLayout *ly = new QHBoxLayout(this);

	ly->addStretch();
	ly->addWidget(bt);
	ly->addStretch();

	//创建老师对象
	te = new Teacher(this);

	//创建学生对象
	st = new Student(this);

	//定义函数指针
	void (Teacher:: *teacherSignal2)(void) = &Teacher::hungry;
	void (Student:: *studentSlot2)(void) = &Student::treat;

	//信号槽绑定
	connect(bt, &QPushButton::clicked, te, teacherSignal2);    //点击按钮,触发信号函数
	connect(te, teacherSignal2, st, studentSlot2);             //信号函数去响应槽函数
}

void MyWidget::ClassOver()
{
	//下课后,老师触发饿了的信号
	emit te->hungry();
}

(5)一个信号可以连接多个槽函数

//信号槽绑定
    connect(bt, &QPushButton::clicked, te, teacherSignal2);        //点击按钮,触发信号
    connect(te, teacherSignal2, st, studentSlot2);                //信号函数去响应槽函数				                               
    connect(bt, &QPushButton::clicked, this, &QWidget::close);     //点击按钮同时关闭窗口



(6)多个按钮连接一个槽函数

//信号槽绑定
	connect(bt1, &QPushButton::clicked, te, teacherSignal2);   //点击按钮,触发信号
	connect(te, teacherSignal2, st, studentSlot2);		   //信号去响应曹函数
	connect(bt1, &QPushButton::clicked, this, &QWidget::close);

	connect(bt2, &QPushButton::clicked, te, teacherSignal2);   //点击按钮,触发信号
	connect(te, teacherSignal2, st, studentSlot2);		   //信号去响应曹函数
	connect(bt2, &QPushButton::clicked, this, &QWidget::close);

猜你喜欢

转载自blog.csdn.net/weixin_41734758/article/details/109165543