QT_C++02-信号和槽函数,Lambda表达式

01 信号槽的基本使用-点击按钮关闭窗口

1.基本原理

QT_C++02-信号和槽函数,Lambda表达式_第1张图片

2.系统信号&系统槽函数的连接

前提条件:创建了窗口,窗口内包含按钮
需求:通过按钮关闭窗口
实现:
 connet(信号发送者,信号(地址),信号接受者,槽函数(地址))
 信号格式: &信号发送者所属类::信号 ,其中信号为系统为信号所属类创建的系统信号
 槽函数格式: &信号接受者所属类别::信号接受者处理信号的槽函数,其中槽函数为系统为信号接收者所属类创建的系统信号

#include "mywidget.h"
//(1)引入按钮头文件
#include "QPushButton"
//引入自定义的按钮
#include 
//引入打印头文件
#include 
myWidget::myWidget(QWidget *parent)
    : QWidget(parent)

{
    //(2)创建第一个按钮:首先引入头文件
    QPushButton *btn=new QPushButton;
    //2.1 显示按钮
    //2.1.1方法:使用show以顶层的方式弹出窗口或控件(新开辟窗口进行显示)
    //btn->show();
    //2.1.2 方法:让窗口或控件依赖在父窗口中(mywidget窗口)
    btn->setParent(this);
    //2.2显示按钮上文本
    btn->setText("第一个按钮");
    //(3)创建第二个按钮:
    //这种方法创建,会按照控件的大小生成窗口,需要重置窗口大小
    QPushButton *btn2=new QPushButton("第二个按钮",this);
    //移动按钮
    btn2->move(100,100);
    //重置窗口大小
    resize(600,400);
    //设置窗口标题
    setWindowTitle("第一个窗口");
    //设置固定窗口大小
     setFixedSize(600,400);
    //设置按钮大小
     btn->resize(100,50);
     //(4)创建自定义按钮的对象
     MyPushButton *btn3=new MyPushButton;
     btn3->setText("自定义按钮");
     btn3->move(100,200);
     btn3->setParent(this);//设置到对象树中

     //(5)
     //需求点击我的按钮,关闭窗口
     //参数1:信号发送者(某个组件,如按钮)
     //参数2:发送的信号
     //     (利用系统的信号,可以查看帮助文档。比如信号发送者是按钮,系统为按钮类设计了相关的信号如点击,长按..)
     //参数3:信号接受者
     //参数4:(信号接受者)处理的槽函数
     //      (利用系统的槽函数,可以参看帮助文档。比如接受者是窗口,系统为窗口设计了相关的槽函数,如关闭,隐藏..)
     connect(btn3,&MyPushButton::clicked,this,&myWidget::close);
     connect(btn2,&QPushButton::clicked,this,&QWidget::close);
   
}
myWidget::~myWidget()
{
    //窗口类对象的析构函数
    qDebug()<<"窗口对象的析构"<

QT_C++02-信号和槽函数,Lambda表达式_第2张图片
详细情况

02 自定义的信号和槽函数

1.自定义信号&自定义槽函数的创建

实现:
connet(信号发送者,信号(地址),信号接受者,槽函数(地址))
信号格式: &信号发送者所属类::信号 ,其中信号为自定义的信号
槽函数格式: &信号接受者所属类别::信号接受者处理信号的槽函数,其中槽函数为自定义信号
QT_C++02-信号和槽函数,Lambda表达式_第3张图片
QT_C++02-信号和槽函数,Lambda表达式_第4张图片
QT_C++02-信号和槽函数,Lambda表达式_第5张图片QT_C++02-信号和槽函数,Lambda表达式_第6张图片
详细情况

信号:
teacher.h:

#ifndef TEACHER_H
#define TEACHER_H

#include 

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

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

};

#endif // TEACHER_H

teacher.cpp:

#include "teacher.h"

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

}

QT_C++02-信号和槽函数,Lambda表达式_第7张图片
槽:
student.h:

#ifndef STUDENT_H
#define STUDENT_H

#include 

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

signals:

public slots:
    //自定义槽函数
    //高版本可以写到public下,或者全局函数
    //槽函数返回值void
    //槽函数需要声明,也需要实现
    //槽函数也可以有参数,可以发生重载
    void treat();
};

#endif // STUDENT_H

student.cpp:

#include "student.h"
#include

Student::Student(QObject *parent) : QObject(parent)
{

}

//槽函数实现
void Student::treat()
{
     qDebug()<<"请老师吃饭"<

QT_C++02-信号和槽函数,Lambda表达式_第8张图片

2.自定义信号&自定义槽函数的连接

在窗口中, 使用槽函数和信号:首先创建信号发送者和信号接受者;然后通过connect建立连接;最后使用emit关键字触发信号,信号将通过连接传给信号接受者启动槽函数
QT_C++02-信号和槽函数,Lambda表达式_第9张图片
widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include"teacher.h"
#include"student.h"

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    Teacher* zt;
    Student* st;

    void classIsOver();

};
#endif // WIDGET_H

QT_C++02-信号和槽函数,Lambda表达式_第10张图片
widget.cpp:

#include "widget.h"

//需求:创建两个类,Teacher类  Student类
//下课后,老师Teacher zt 会发出一个信号,饿了
//学生响应信号Student st,处理信号的槽函数,请客吃饭

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    zt = new Teacher(this);
    st =new Student(this);

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

    //下课
    classIsOver();
}

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

Widget::~Widget()
{
}

03 重载的自定义信号&自定义槽函数

1.创建重载的自定义信号&自定义槽函数

QT_C++02-信号和槽函数,Lambda表达式_第11张图片
teacher.h:

#ifndef TEACHER_H
#define TEACHER_H

#include 

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

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

    void hungry(QString foodName);

};

#endif // TEACHER_H

QT_C++02-信号和槽函数,Lambda表达式_第12张图片
teacher.h:

#ifndef TEACHER_H
#define TEACHER_H

#include 

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

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

    void hungry(QString foodName);
};

#endif // TEACHER_H

QT_C++02-信号和槽函数,Lambda表达式_第13张图片
teacher.cpp:

#include "student.h"
#include

Student::Student(QObject *parent) : QObject(parent)
{

}

//槽函数实现
void Student::treat()
{
     qDebug()<<"请老师吃饭"<

2.连接重载的自定义信号&槽函数

使用有参的槽函数和信号:
需要明确(重载)信号和(重载)槽函数的地址:例 void (Teacher::*teacherSignal )(QString)=&Teacher::hungry---------》代表参数为QString的重载函数的地址

QT_C++02-信号和槽函数,Lambda表达式_第14张图片
widget.cpp:

#include "widget.h"

//需求:创建两个类,Teacher类  Student类
//下课后,老师Teacher zt 会发出一个信号,饿了
//学生响应信号Student st,处理信号的槽函数,请客吃饭

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    zt = new Teacher(this);
    st =new Student(this);

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

    //有参数,信号和槽函数
    //函数指针,执行函数地址
    void(Teacher:: *teacherSignal)(QString)=&Teacher::hungry;
    void(Student::* stSlot)(QString)=&Student::treat;
    connect(zt,teacherSignal,st,stSlot);

    //下课
    classIsOver();
}

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

    emit zt->hungry("宫爆鸡丁");
}

Widget::~Widget()
{
}

在这里插入图片描述

使用无参的槽函数和信号:需要明确(重载)信号和(重载)槽函数的地址:例 void (Teacher::*teacherSignal )(void)=&Teacher::hungry---------》代表无参的函数的地址
代码:connect(信号发送者,无参信号(地址),信号接受者,无参槽函数(地址)
QT_C++02-信号和槽函数,Lambda表达式_第15张图片

#include "widget.h"

//需求:创建两个类,Teacher类  Student类
//下课后,老师Teacher zt 会发出一个信号,饿了
//学生响应信号Student st,处理信号的槽函数,请客吃饭

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    zt = new Teacher(this);
    st =new Student(this);

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

    //有参数,信号和槽函数
    //函数指针,执行函数地址
    void(Teacher:: *teacherSignal)(QString)=&Teacher::hungry;
    void(Student::* stSlot)(QString)=&Student::treat;
    connect(zt,teacherSignal,st,stSlot);

    //下课
    classIsOver();

    //无参的槽函数和信号建立连接
    void (Teacher::*teacherSignal1 )(void)=&Teacher::hungry;//将无参的信号的地址付给teacherSignal
    void (Student ::*studentSlot1 )(void)=&Student::treat;//将无参的槽函数付给studentSlot
    connect(zt,teacherSignal1,st,studentSlot1);

    //调用下课函数
    classIsOver();//调用classisover函数,该函数用于触发老师
      //饿了的信号,因为上面信号做了一个连接,所以信号被信号接收者
      //接收,然后调用槽函数
}

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

    //emit zt->hungry("宫爆鸡丁");
}

Widget::~Widget()
{
}

04 信号&信号连接

1.信号连接信号

代码:connect(信号发送者,信号(地址),信号接受者,信号(地址))
流程:一个按钮点击信号——>触发第一个连接的信号——>该信号触发另一个连接的槽函数
QT_C++02-信号和槽函数,Lambda表达式_第16张图片
widget.cpp:

#include "widget.h"
#include

//需求:创建两个类,Teacher类  Student类
//下课后,老师Teacher zt 会发出一个信号,饿了
//学生响应信号Student st,处理信号的槽函数,请客吃饭

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    zt = new Teacher(this);
    st =new Student(this);

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

    //有参数,信号和槽函数
    //函数指针,执行函数地址
   // void(Teacher:: *teacherSignal)(QString)=&Teacher::hungry;
//    void(Student::* stSlot)(QString)=&Student::treat;
//    connect(zt,teacherSignal,st,stSlot);

//    //下课
//    classIsOver();

//    //无参的槽函数和信号建立连接
//    void (Teacher::*teacherSignal1 )(void)=&Teacher::hungry;//将无参的信号的地址付给teacherSignal
//    void (Student ::*studentSlot1 )(void)=&Student::treat;//将无参的槽函数付给studentSlot
//    connect(zt,teacherSignal1,st,studentSlot1);

//    //调用下课函数
//    classIsOver();//调用classisover函数,该函数用于触发老师
//      //饿了的信号,因为上面信号做了一个连接,所以信号被信号接收者
//      //接收,然后调用槽函数

    //点击按钮,才下课
    QPushButton* btn = new QPushButton("下课",this);
    //触发无参信号和槽
    //信号连接信号
    void (Teacher:: *teacherSignal1 )(void)=&Teacher::hungry;
    void (Student :: *studentSlot1 )(void)=&Student::treat;
    connect(btn,&QPushButton::clicked,zt,teacherSignal1);
    connect(zt,teacherSignal1,st,studentSlot1);

    //重置大小
    resize(600,400);
}

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

    //emit zt->hungry("宫爆鸡丁");
}

Widget::~Widget()
{
}

QT_C++02-信号和槽函数,Lambda表达式_第17张图片

2.信号断开信号

代码:disconnect(信号发送者,信号,信号接受者,信号)
QT_C++02-信号和槽函数,Lambda表达式_第18张图片

#include "widget.h"
#include

//需求:创建两个类,Teacher类  Student类
//下课后,老师Teacher zt 会发出一个信号,饿了
//学生响应信号Student st,处理信号的槽函数,请客吃饭

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    zt = new Teacher(this);
    st =new Student(this);

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

    //有参数,信号和槽函数
    //函数指针,执行函数地址
   // void(Teacher:: *teacherSignal)(QString)=&Teacher::hungry;
//    void(Student::* stSlot)(QString)=&Student::treat;
//    connect(zt,teacherSignal,st,stSlot);

//    //下课
//    classIsOver();

//    //无参的槽函数和信号建立连接
//    void (Teacher::*teacherSignal1 )(void)=&Teacher::hungry;//将无参的信号的地址付给teacherSignal
//    void (Student ::*studentSlot1 )(void)=&Student::treat;//将无参的槽函数付给studentSlot
//    connect(zt,teacherSignal1,st,studentSlot1);

//    //调用下课函数
//    classIsOver();//调用classisover函数,该函数用于触发老师
//      //饿了的信号,因为上面信号做了一个连接,所以信号被信号接收者
//      //接收,然后调用槽函数

    //点击按钮,才下课
    QPushButton* btn = new QPushButton("下课",this);
    //触发无参信号和槽
    //信号连接信号
    void (Teacher:: *teacherSignal1 )(void)=&Teacher::hungry;
    void (Student :: *studentSlot1 )(void)=&Student::treat;
    connect(btn,&QPushButton::clicked,zt,teacherSignal1);
    connect(zt,teacherSignal1,st,studentSlot1);

    //断开信号和槽
    disconnect(zt,teacherSignal1,st,studentSlot1)

    //重置大小
    resize(600,400);
}

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

    //emit zt->hungry("宫爆鸡丁");
}

Widget::~Widget()
{
}

QT_C++02-信号和槽函数,Lambda表达式_第19张图片

05 信号和槽拓展

(1)信号可以连接信号
(2)信号和槽可以断开 discount
(3)一个信号可以连接多个槽函数
(4)多个信号可以连接一个槽函数
(5)信号和槽函数的参数必须类型一一对应
(6)信号和槽函数的参数个数不需要一致,信号参数个数可以多余槽函数参数个数,并且槽函数的参数与信号的参数类型一致,反之不可以
QT_C++02-信号和槽函数,Lambda表达式_第20张图片

06 Lambda表达式

1.基础概念

C++11中,Lambda表达式用于定义并创建匿名函数对象,以简化编程工作。Lambda表达式的基本构成:

[ capture ] ( parameters ) mutable ->return-type { statement };

[ 函数对象参数 ] ( 操作符重载函数参数) mutable ->返回值 { 函数体 };
参数:
(1)函数对象参数[ ]: []标识一个lambda函数的开始,不能省略,函数对象参数是传递给编译器自动生成的函数对象类的构造函数的,函数对象参数只能使用那些定义Lambda为止时Lambda所在作用范围内可见的局部变量(包括Lambda所在类的this),函数对象参数有以下几个形式:

  • [ ]:没有使用任何函数对象参数

  • [=]:函数体内可以使用函数所在作用域范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)推荐值传递方式
    QT_C++02-信号和槽函数,Lambda表达式_第21张图片

  • [&]: 函数体内可以使用函数所在作用域范围内所有可见的局部变量(包括Lambda所在类的this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)推荐值传递

  • [this]:函数体内,可以使用函数所在类中的成员变量

  • [a]:将a进行按值传递,并且按值传递时,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的,要修改传递进来的a的拷贝,可以添加mutable修饰符

  • [&a]:将a进行按引用传递

  • [=,&a]:除了a按引用,其他都是按值
    (2) 操作符重载函数参数(): 标识重载的()操作符的参数,没有参数时,这部分可以省略,参数可以通过按值和按引用两种方式进行传递
    (3)mutible可修改标识符: mutible声明,按值传递函数对象时,加上mutable修饰符后,可以修改按值传递进来的拷贝(注意是修改拷贝,不是值本身),否则始终不可修改
    QT_C++02-信号和槽函数,Lambda表达式_第22张图片
    (4)返回值类型(函数返回值): 当返回值为void类型时,或者函数体中只有一处return的地方时,这部分可以省略
    QT_C++02-信号和槽函数,Lambda表达式_第23张图片(5) 函数体 {}: 这部分不可以省略,但是可以为空

2.Lambda函数使用案例

需求:利用Lambda函数表达式,实现点击按钮关闭窗口
QT_C++02-信号和槽函数,Lambda表达式_第24张图片

#include "widget.h"
#include
#include

//需求:创建两个类,Teacher类  Student类
//下课后,老师Teacher zt 会发出一个信号,饿了
//学生响应信号Student st,处理信号的槽函数,请客吃饭

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QPushButton *btn1=new QPushButton;
     btn1->setParent(this);
     btn1->setText("第一个按钮");

     QPushButton *btn2=new QPushButton;
     btn2->setParent(this);
     btn2->setText("第二个按钮");
     btn2->move(200,200);

     //lambda函数声明
 //    [=](){
 //        btn1->setText("改名第一个按钮");
 //        btn2->setText("改名第二个按钮");

 //    };

     [=](){
         btn1->setText("改名第一个按钮");
         btn2->setText("改名第二个按钮");
     }();

     //mutable关键字
     QPushButton *btn3=new QPushButton;
     btn3->setParent(this);
     btn3->setText("按钮1");
     btn3->move(300,0);

     QPushButton *btn4=new QPushButton;
     btn4->setParent(this);
     btn4->setText("按钮2");
     btn4->move(300,100);
     int a=10;
     connect(btn3,&QPushButton::clicked,this,
             [a]()mutable{a=a+100;qDebug()<返回值类型
     int b=[]()->int {return 100;}();
     qDebug()<setParent(this);
     btn5->setText("lambda案例");
     btn5->move(500,200);
     //做信号槽函数,默认内部变量会进行锁状态,只读状态,如果进行写操作,就会挂掉
     connect(btn5,&QPushButton::clicked,this,[=]()
     {
         this->close();
         //关闭窗口的代码,也可以填入槽函数,或者信号等。。。
     });
}

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

    //emit zt->hungry("宫爆鸡丁");
}

Widget::~Widget()
{
}

QT_C++02-信号和槽函数,Lambda表达式_第25张图片

你可能感兴趣的:(#,Qt,qt,开发语言)