#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的开始,这部分必须存在不能省略.
-
空: 没有使用任何函数对象参数
-
=:函数体内可以使用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类型