Qt中的元对象系统提供了对象间通信的信号和槽机制、运行时类型信息和动态属性系统。
使用元对象系统需要满足三个条件:
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
- #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
- #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;
- }

点击之后

这里需要解决的问题:输出的结果带有 " "
解决方法为:
c++11中新加的lambda表达式
格式为:
- [ 函数对象参数 ](操作符重载函数参数) mutable ->return-type
-
- {
-
- 内容
-
- }
| 函数对象参数 | 含义 |
| 空 | 没有函数对象参数 |
| = | 可以使用lambda范围内的所有可见的局部变量 ,以值传递的方式 |
| & | 与 this 大体相同 以引用的方式传递 一般不使用& 会造成内存泄漏 |
| this | 可以使用lambda中的成员变量 |
| a | 将a 按值传递 默认不能修改(const) 可以在 操作符重载函数参数后加 mutable |
| &a | 以引用的方式 |
- mutable 按值传递对象参数时加上mutable 可以 修改按值传递进来的拷贝(修改拷贝 不是修改值本身)
- 以上的参数可以混合使用
1.可以代替槽函数:实现两个页面的跳转
主页面为widget 副页面为:person(继承于QWidget)
大致思路:
- 在widget中,先创建一个person对象,和一个QPushButton控件
- connect()实现widget到person的跳转
- 在person中,添加信号和触发信号的函数,和一个QPushButton控件
- connect() 实现点击,执行触发函数
- 在widget中,再一个connect(),信号函数为person中的信号,槽函数为lambda表达式,实现页面隐藏和页面显示。
person.h
- #ifndef PERSON_H
- #define PERSON_H
-
- #include
-
- 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
- #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;