• 信号与槽和lambda表达式


    QT元对象系统:

    Qt中的元对象系统提供了对象间通信的信号和槽机制、运行时类型信息和动态属性系统。

    使用元对象系统需要满足三个条件:

    • 只有QObject派生类才可以使用元对象系统特性。
    • 在类声明前使用Q_OBJECT()宏来开启元对象功能。
    • 使用Moc工具为每个QObject派生类提供实现代码。

    QObject派生类之间的转换:

    1. QObject *obj = new QWidget();
    2. QWidget *widget = qobject_cast<Qwidget *>(obj);

    详解可进下面的链接:

    Qt中的元对象系统(Meta-Object System) - 知乎 (zhihu.com)

     

    信号与槽:

    信号与槽:简单的说,就是发送信号,然后用槽函数接收信号。

    信号(Signal)就是在特定情况下被发射的事件。

    槽函数(Slot)就是对信号响应的函数。

    连接函数为:connect()

    QT4的方法:(旧版本的)

    QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));

    1. QPushButton *p1=new QPushButton(this);
    2. connect(p1,SIGNAL(clicked()),this,SLOT(close()));//点击关闭窗口
    3. //connect(信号发送者, 发送的信号, 信号的接收者 ,处理的槽函数)

    优点:参数直观

    缺点:编译器不会检测参数类型

    QT5的方法为:

    QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection)

    1. connect(p1,&QPushButton::clicked,this,&Widget::close);
    2. //connect(信号发送者, 发送的信号, 信号的接收者 ,处理的槽函数)
    3. connect(p1,&QPushButton::clicked,&Widget::close);//this可以省略

     信号的特点:

    • 写在 signals:后面
    • 返回值为 void
    • 不需要实现、可以有参、可以重载

    槽函数的特点:

    • 写在public 或 全局函数下
    • 返回值为void
    • 需要实现、可以有参、可以重载

    信号与槽的特点:

    • 信号可以连接信号
    • 一个信号可以连接多个槽函数
    • 多个信号可以连接一个槽函数
    • 信号和槽的类型必须一致
    • 信号参数可以多于槽函数 但参数类型必须一致

    自定义信号和槽函数

    触发信号的关键词    emit   signal();

    实现功能:点击按钮,触发信号,执行槽函数 

    widget.h文件

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include"person.h"
    5. QT_BEGIN_NAMESPACE
    6. namespace Ui { class Widget; }
    7. QT_END_NAMESPACE
    8. class Widget : public QWidget
    9. {
    10. Q_OBJECT
    11. public:
    12. Widget(QWidget *parent = nullptr);
    13. ~Widget();
    14. void debug();//槽函数
    15. void show_emit();//触发函数
    16. private:
    17. Ui::Widget *ui;
    18. signals:
    19. void show();//信号函数
    20. };
    21. #endif // WIDGET_H

     widget.cpp文件

    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. #include<QPushButton>
    4. #include<QDebug>
    5. Widget::Widget(QWidget *parent)
    6. : QWidget(parent)
    7. , ui(new Ui::Widget)
    8. {
    9. ui->setupUi(this);
    10. //p1=new person;
    11. setFixedSize(600,600);
    12. QPushButton *pbt=new QPushButton(this);//创建一个按键
    13. pbt->move(200,200);//移动按键位置
    14. pbt->setText("点击");//设置按键信息
    15. connect(pbt,&QPushButton::clicked,this,&Widget::show_emit);//点击按钮触发信号
    16. connect(this,&Widget::showdata,this,&Widget::debug);//接收信号,执行槽函数
    17. }
    18. void Widget::show_emit()
    19. {
    20. emit showdata();//发射信号
    21. }
    22. void Widget::debug()//槽函数
    23. {
    24. qDebug()<<"1231231230";//输出一串数字
    25. }
    26. Widget::~Widget()
    27. {
    28. delete ui;
    29. }

     点击按钮后:显示一串数字

     

     当信号和槽有重载时的处理:

    需要把信号或槽转化为函数指针

    1. //函数指针
    2. //返回类型(类名:: *名称)(参数类型)=&类名::函数名

    widget.h文件

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include"person.h"
    5. QT_BEGIN_NAMESPACE
    6. namespace Ui { class Widget; }
    7. QT_END_NAMESPACE
    8. class Widget : public QWidget
    9. {
    10. Q_OBJECT
    11. public:
    12. Widget(QWidget *parent = nullptr);
    13. ~Widget();
    14. void debug();//槽函数
    15. void debug(QString a);//重载
    16. void show_emit();//触发函数
    17. signals:
    18. void showdata();//信号函数
    19. void showdata(QString a);//重载
    20. private:
    21. Ui::Widget *ui;
    22. };
    23. #endif // WIDGET_H

     widget.cpp文件

     

    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. #include<QPushButton>
    4. #include<QDebug>
    5. Widget::Widget(QWidget *parent)
    6. : QWidget(parent)
    7. , ui(new Ui::Widget)
    8. {
    9. ui->setupUi(this);
    10. //p1=new person;
    11. setFixedSize(600,600);
    12. QPushButton *pbt=new QPushButton(this);//创建一个按键
    13. pbt->move(200,200);//移动按键位置
    14. pbt->setText("点击");//设置按键信息
    15. connect(pbt,&QPushButton::clicked,this,&Widget::show_emit);//点击按钮触发信号
    16. void (Widget:: *k1)(QString)=&Widget::debug;//debug的函数指针
    17. void(Widget:: *k2)(QString)=&Widget::showdata;//showdata的函数指针
    18. connect(this,k2,this,k1);//接收信号,执行槽函数
    19. }
    20. void Widget::show_emit()
    21. {
    22. emit showdata("故此");//发射有参信号
    23. }
    24. void Widget::debug()//槽函数
    25. {
    26. qDebug()<<"1231231230";//输出字符串
    27. }
    28. void Widget::debug(QString a)//槽函数
    29. {
    30. qDebug()<<a;//输出字符串
    31. }
    32. Widget::~Widget()
    33. {
    34. delete ui;
    35. }

     点击之后

    这里需要解决的问题:输出的结果带有 "  "

    解决方法为:

    • 把qDebug()<
    • .toUtf8() :QString转化为QBateArray型
    • .data()    :QBateArray转化为QChar*型

     

    lambda 表达式

    c++11中新加的lambda表达式 

    格式为:

    1. [ 函数对象参数 ](操作符重载函数参数) mutable ->return-type
    2. {
    3. 内容
    4. }
    函数对象参数含义
    没有函数对象参数
    =可以使用lambda范围内的所有可见的局部变量 ,以值传递的方式
    与   this 大体相同         以引用的方式传递  一般不使用& 会造成内存泄漏
    this可以使用lambda中的成员变量
     将a 按值传递 默认不能修改(const) 可以在  操作符重载函数参数后加 mutable
    &a以引用的方式
    • mutable   按值传递对象参数时加上mutable 可以 修改按值传递进来的拷贝(修改拷贝 不是修改值本身)
    • 以上的参数可以混合使用

    lambda表达式的用法: 

    1.可以代替槽函数:实现两个页面的跳转

    主页面为widget    副页面为:person(继承于QWidget)

    大致思路:

    1. 在widget中,先创建一个person对象,和一个QPushButton控件
    2. connect()实现widget到person的跳转
    3. 在person中,添加信号和触发信号的函数,和一个QPushButton控件
    4. connect() 实现点击,执行触发函数
    5. 在widget中,再一个connect(),信号函数为person中的信号,槽函数为lambda表达式,实现页面隐藏和页面显示。

    person.h

    1. #ifndef PERSON_H
    2. #define PERSON_H
    3. #include
    4. class person : public QWidget
    5. {
    6. Q_OBJECT
    7. public:
    8. explicit person(QWidget *parent = nullptr);
    9. void backemit();//出发信号
    10. signals:
    11. void back();//返回的信号
    12. };
    13. #endif // PERSON_H

    person.cpp

    1. #include "person.h"
    2. #include<QPushButton>
    3. person::person(QWidget *parent) : QWidget(parent)
    4. {
    5. setFixedSize(600,600);//重置大小
    6. QPushButton *pbt1=new QPushButton(this);
    7. pbt1->move(200,200);//移动按键位置
    8. pbt1->setText("返回widget");//设置按键信息
    9. connect(pbt1,&QPushButton::clicked,this,&person::backemit);//点击按键,发送信号
    10. }
    11. void person::backemit()
    12. {
    13. emit back();//发射信号
    14. }

    widget.h

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include"person.h"
    5. QT_BEGIN_NAMESPACE
    6. namespace Ui { class Widget; }
    7. QT_END_NAMESPACE
    8. class Widget : public QWidget
    9. {
    10. Q_OBJECT
    11. public:
    12. Widget(QWidget *parent = nullptr);
    13. ~Widget();
    14. signals:
    15. private:
    16. Ui::Widget *ui;
    17. person *p1=nullptr;
    18. };
    19. #endif // WIDGET_H

    widget.cpp

    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. #include<QPushButton>
    4. #include<QDebug>
    5. Widget::Widget(QWidget *parent)
    6. : QWidget(parent)
    7. , ui(new Ui::Widget)
    8. {
    9. ui->setupUi(this);
    10. setFixedSize(600,600);
    11. QPushButton *pbt=new QPushButton(this);//创建一个按键
    12. pbt->move(200,200);//移动按键位置
    13. pbt->setText("点击");//设置按键信息
    14. p1=new person;//初始化对象
    15. connect(pbt,&QPushButton::clicked,[=]()//lambda表达式
    16. {
    17. this->hide();//隐藏窗口
    18. p1->show();
    19. });
    20. connect(p1,&person::back,this,[=]()
    21. {
    22. this->show();//显示自身
    23. p1->hide();//p1隐藏
    24. });
    25. }
    26. Widget::~Widget()
    27. {
    28. delete ui;
    29. }

    2.参数列表使用

    1. QPushButton *P=new QPushButton("按钮1",this);
    2. //因为clicked有一个返回值 为bool类型 所以可以接受这个值
    3. connect(P,&QPushButton::clicked,[=](bool clicked)
    4. {
    5. qDebug()<<"clicked="<<clicked;
    6. });

    3.mutable的使用

    1.     QPushButton *P=new QPushButton("按钮1",this);
    2.     int a=10;
    3.     //未加mutable时 lambda中的变量只是可读
    4.     //添加mutable后 lambda中的变量变为 可读可写
    5.     connect(P,&QPushButton::clicked,[=]()mutable
    6.     {
    7.             a+=10;
    8.             qDebug()<<"a在lamba中的值="<<a;
    9.     });
    10.     //说明修改的仅仅是拷贝
    11.     qDebug()<<"a在lambda外的值="<<a;

  • 相关阅读:
    建筑设计资质怎么办理,建筑设计乙级资质申请条件有哪些
    HTTP四大参数类型及请求参数的方式和如何接收
    《软件方法》自测题解析-006:误以为是业务建模
    数据结构与算法_大数据处理_求topK的两种求解方法
    服务器是什么 服务器能干什么
    c++ 学习之 强制类型转换运算符 const_cast
    Jmeter —— 常用的几种断言方法(基本用法)
    AbortController中止请求通信[模糊搜索案例]
    RSA的C++语言描述简单实现
    C# Onnx Yolov8 Cls 分类
  • 原文地址:https://blog.csdn.net/qq_45303986/article/details/127673452