信号与槽和lambda表达式

QT元对象系统:

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

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

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

QObject派生类之间的转换:

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

详解可进下面的链接:

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

 

信号与槽:

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

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

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

连接函数为:connect()

QT4的方法:(旧版本的)

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

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

优点:参数直观

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

QT5的方法为:

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

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

 信号的特点:

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

槽函数的特点:

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

信号与槽的特点:

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

自定义信号和槽函数

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

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

widget.h文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include"person.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

    void debug();//槽函数
    void show_emit();//触发函数

private:
    Ui::Widget *ui;
signals:
    void show();//信号函数
};
#endif // WIDGET_H

 widget.cpp文件

#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //p1=new person;
    setFixedSize(600,600);
    QPushButton *pbt=new QPushButton(this);//创建一个按键
    pbt->move(200,200);//移动按键位置
    pbt->setText("点击");//设置按键信息
    connect(pbt,&QPushButton::clicked,this,&Widget::show_emit);//点击按钮触发信号
    connect(this,&Widget::showdata,this,&Widget::debug);//接收信号,执行槽函数
}

void Widget::show_emit()
{
    emit showdata();//发射信号
}
void Widget::debug()//槽函数
{
    qDebug()<<"1231231230";//输出一串数字
}
Widget::~Widget()
{
    delete ui;
}

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

 

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

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

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

widget.h文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include"person.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

    void debug();//槽函数
    void debug(QString a);//重载
    void show_emit();//触发函数
signals:
    void showdata();//信号函数
    void showdata(QString a);//重载
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

 widget.cpp文件

 

#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //p1=new person;
    setFixedSize(600,600);
    QPushButton *pbt=new QPushButton(this);//创建一个按键
    pbt->move(200,200);//移动按键位置
    pbt->setText("点击");//设置按键信息
    connect(pbt,&QPushButton::clicked,this,&Widget::show_emit);//点击按钮触发信号

    void (Widget:: *k1)(QString)=&Widget::debug;//debug的函数指针
    void(Widget:: *k2)(QString)=&Widget::showdata;//showdata的函数指针
    connect(this,k2,this,k1);//接收信号,执行槽函数
}

void Widget::show_emit()
{
    emit showdata("故此");//发射有参信号
}

void Widget::debug()//槽函数
{
    qDebug()<<"1231231230";//输出字符串
}
void Widget::debug(QString a)//槽函数
{
    qDebug()<<a;//输出字符串
}
Widget::~Widget()
{
    delete ui;
}

 点击之后

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

解决方法为:

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

 

lambda 表达式

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

格式为:

[ 函数对象参数 ](操作符重载函数参数)  mutable ->return-type

{

内容

}
函数对象参数含义
没有函数对象参数
=可以使用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

#ifndef PERSON_H
#define PERSON_H

#include <QWidget>

class person : public QWidget
{
    Q_OBJECT
public:
    explicit person(QWidget *parent = nullptr);
    void backemit();//出发信号

signals:
    void back();//返回的信号
};

#endif // PERSON_H

person.cpp

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

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include"person.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private:
    Ui::Widget *ui;
    person *p1=nullptr;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setFixedSize(600,600);
    QPushButton *pbt=new QPushButton(this);//创建一个按键
    pbt->move(200,200);//移动按键位置
    pbt->setText("点击");//设置按键信息
    p1=new person;//初始化对象
    connect(pbt,&QPushButton::clicked,[=]()//lambda表达式
    {
        this->hide();//隐藏窗口
        p1->show();
    });
    connect(p1,&person::back,this,[=]()
    {
        this->show();//显示自身
        p1->hide();//p1隐藏

    });

}

Widget::~Widget()
{
    delete ui;
}

2.参数列表使用

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

3.mutable的使用

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

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值