Qt信号和槽

在这里插入图片描述

#include "mywidget.h"
#include "qpushbutton.h"

myWidget::myWidget(QWidget *parent)
    : QWidget(parent)
{
    //创建按钮
    QPushButton *btn=new QPushButton();
    btn->setParent(this);  //show方法显示的是顶层窗口 btn的show方法会把btn单独显示在窗口外面
    btn->setText("第一个按钮");
    //需求 点击按钮关闭窗口
    connect(btn,                     //信号的发送者
            &QPushButton::clicked,   //发送的信号	//这里只能使用QPushButton 而不能使用实例化对象btn
            this,                    //信号的接收者	//信号接收者可以是一个类 
            &myWidget::close         //处理的槽函数
            );


    //设置窗口标题
    setWindowTitle("第一个QT程序");
}

myWidget::~myWidget()
{

}

connect函数把按钮的点击事件和窗口的处理函数close关联了起来。

需要注意的是:发送的信号函数的参数个数一定要比槽函数的参数多,且类型一样,否则会报错.


自定义信号和槽

1:信号函数的编写

signals:
    //自定义信号 写道signals下
    //返回值时 void 只需要申明 不需要实现
    //可以有参数 可以重载
    void hungry();

2:槽函数的编写

.h类定义
public slots:
    //qt5.0以后 槽函数可以写在public下,也可以是全局函数
    //返回值void 需要申明 也需要实现
    //可以有参数 可以重载
    void treat();
};

.cpp类实现
void Student::treat()
{
    qDebug()<<"请老师吃饭";
}

3:使用connect连接

 connect(yxp,&Teacher::hungry,ly,&Student::treat);

4:发射信号
也就是调用到hungry函数

 //emit 代表要发射信号了 是一个宏定义  为空 
void myWidget::clasIsOver()
{
  emit  yxp->hungry();
}

自定义的信号和槽发生重载的解决

当信号函数或者槽函数有重载的情况时,在connect时,需要定义函数指针的方式明确是哪一个重载函数。

例如:

#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

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

signals:
    //自定义信号 写道signals下
    //返回值时 void 只需要申明 不需要实现
    //可以有参数 可以重载
    void hungry();
    void hungry(QString);		//在这里有重载的情况
public slots:
};

#endif // TEACHER_H
#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

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

signals:
    //自定义信号 写道signals下
    //返回值时 void 只需要申明 不需要实现
    //可以有参数 可以重载
public slots:
    //qt5.0以后 槽函数可以写在public下,也可以是全局函数
    //返回值void 需要申明 也需要实现
    //可以有参数 可以重载
    void treat();
    void treat(QString foodName);
};

#endif // STUDENT_H

// 构造函数的实现在cpp中
void Student::treat()
{
    qDebug()<<"请老师吃饭";
}

void Student::treat(QString foodName)
{
     qDebug()<<"请老师吃饭,老师要吃"<<foodName.toUtf8().data();
}

窗口类包含测试的两个类指针

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>
#include "teacher.h"
#include "student.h"
class myWidget : public QWidget
{
    Q_OBJECT

private:
    Teacher *yxp;
    Student *ly;
public:
    myWidget(QWidget *parent = 0);
    void clasIsOver();
    ~myWidget();
};

#endif // MYWIDGET_H

在窗口类的构造函数中,实现的发射信号

#include "mywidget.h"
#include "qpushbutton.h"


myWidget::myWidget(QWidget *parent)
    : QWidget(parent)
{
    //创建一个老师对象
    this->yxp=new Teacher(this);
    //创建一个学生对象
    this->ly=new Student(this);

    //定义函数指针 重载时就必须这样指明要调用的是哪一个函数
    void (Teacher::*teacherSingal)(QString)=&Teacher::hungry;
    void (Student::*studentSlot)(QString)=&Student::treat;

    connect(yxp,teacherSingal,ly,studentSlot);
    clasIsOver();
}

void myWidget::clasIsOver()
{
    //emit 代表要发射信号了 是一个宏定义  为空
   emit yxp->hungry("鱼香肉丝");
}

myWidget::~myWidget()
{

}

信号连接信号

创建一个按钮,点击按钮发送信号,在这里用类的成员函数当成槽函数.

myWidget::myWidget(QWidget *parent)
    : QWidget(parent)
{
    //创建一个老师对象
    this->yxp=new Teacher(this);
    //创建一个学生对象
    this->ly=new Student(this);

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

    connect(yxp,teacherSingal,ly,studentSlot);
    QPushButton *btn=new QPushButton("点击触发信号",this);
    this->resize(600,400);
    
    //信号连接信号,这里使用没有参数的teacherSingal是因为QPushButton::clicked的参数为bool类型.而我们自己定义的信号teacherSingal有参数是QString的.
	//会产生类型不匹配的问题 ,这里值得注意
    connect(btn,&QPushButton::clicked,yxp,teacherSingal);

}

信号断开连接

关闭指定对象的所有信号

  disconnect(myObject, 0, 0, 0);

等同于下面的写法

  myObject->disconnect();

关闭指定信号的所有连接

  disconnect(myObject, SIGNAL(mySignal()), 0, 0);

等同于下面的写法

  myObject->disconnect(SIGNAL(mySignal()));

断开指定的接收者的连接

  disconnect(myObject, 0, myReceiver, 0);

等同于下面的写法

  myObject->disconnect(myReceiver);

Lambda表达式

c++11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作

[函数对象参数](操作符重载函数参数)mutable->返回值{函数体}

[]:函数对象参数标志一个Lambda的开始,这部分必须存在不能省略.

  1. 空: 没有使用任何函数对象参数

  2. =:函数体内可以使用Lambda所在作用范围内所有课件的局部变量,(包括Lambda所在类的this),并且是值传递方式,所有的局部变量都是只读,不可以修改的.

3)&:函数体内可以使用Lambda所在作用范围内所有课件的局部变量,(包括Lambda所在类的this),并且是引用传递方式,修改传过来的值,会影响原来的局部变量.可以修改外部传过来的局部变量.

4)a :把局部变量a按值传入函数体中,函数体中只能使用该变量

5)&a :把局部变量a引用传递到函数体中,函数体中只能使用该变量,可以修改该变量的值,外部也会改变.

6)mutable:该关键字的作用是表明可以修改按值传递进来的拷贝,而不是值本身.(内部修改,不影响外部),

myWidget::myWidget(QWidget *parent)
    : QWidget(parent)
{
    QPushButton *btn=new QPushButton("点击触发信号",this);
    this->resize(600,400);

    [=](){btn->setText("修改按钮");}();//最后加的(),代表调用一次匿名函数
}

在connect函数中使用Lambda表达式


   //connect函数最后一个参数可以使用Lambda表达式,更加易于传参数进去,因为有时候信号会限制槽函数的参数类型及个数.
    //而使用Lambda表达式完美的解决了这个问题
    connect(btn,&QPushButton::clicked,this,[=](){ emit clasIsOver();});

返回值

  int ret=[]()->int{return 0;}();  //->int  表明返回值是int类型
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值