您的位置:首页 > 汽车 > 新车 > 微信公众号怎么创建桌面快捷方式_推广关键词如何优化_黄页88网络营销宝典_网站建站价格

微信公众号怎么创建桌面快捷方式_推广关键词如何优化_黄页88网络营销宝典_网站建站价格

2024/11/15 7:53:58 来源:https://blog.csdn.net/ZJQSDSA/article/details/142501491  浏览:    关键词:微信公众号怎么创建桌面快捷方式_推广关键词如何优化_黄页88网络营销宝典_网站建站价格
微信公众号怎么创建桌面快捷方式_推广关键词如何优化_黄页88网络营销宝典_网站建站价格

目  录

一、元对象系统简介

二、信号和槽

三、类型信息

四、动态设置属性


一、元对象系统简介

QT中的元对象系统Q_OBJECT并不是C++标准代码,因此在使用时需要QT的MOC(元对象编译器)进行预处理,MOC会在编译时期读取C++代码中的特定宏(如Q_OBJECT),再由标准的C++编译器进行重新编译。

Q_OBJECT的使用:必须要在类中定义元对象系统Q_OBJECT 宏才能使用(在类定义时,如果没有指定public或者private,则默认为private(私有))。程序运行时,moc会扫描此类,并生成元对象信息,包括但不限于类名、父类、属性、信号、槽函数等;

Q_OBJECT的特性:

  • 类型信息:Qt使用元对象系统来存储关于对象的信息,如类名和父类。
  • 属性系统:支持动态的属性机制,允许在运行时查询和修改对象的属性。
  • 信号和槽的动态连接:元对象系统允许在运行时创建和解除信号与槽之间的连接。

二、信号和槽

(1)信号与槽是对象间进行通信的机制,使用QObject::connect函数连接信号和槽时,元对象系统会在运行时查找信号(signals)和槽(slots),并建立连接。使用方式如下:定义两个类,名为QtWidgetsApplication3、obj,互相通信。

QtWidgetsApplication3.h

#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication3.h"
#include <QObject> //包含头文件,以使用信号槽class QtWidgetsApplication3 : public QMainWindow
{//启用Qt的元对象系统,允许使用信号和槽等特性Q_OBJECT //默认私有
public:QtWidgetsApplication3(QWidget *parent = nullptr);~QtWidgetsApplication3();
private:Ui::QtWidgetsApplication3Class ui;
signals:    //声明信号void testsignal();
};class obj : public QObject //继承QObject使用信号槽
{//启用Qt的元对象系统,允许使用信号和槽等特性Q_OBJECT 
public: //声明构造函数,接受一个QObject指针作为父对象obj(QObject* parent = nullptr);
public slots: //声明槽void testslot();
};

QtWidgetsApplication3.cpp

#include "QtWidgetsApplication3.h"
QtWidgetsApplication3::QtWidgetsApplication3(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);obj* qobj = new obj(this);  //创建obj的实例QObject::connect(this,&QtWidgetsApplication3::testsignal, qobj,&obj::testslot); //连接信号和槽emit testsignal();          //触发信号
}void obj::testslot()
{   qDebug() << "obj::testslot()";   }QtWidgetsApplication3::~QtWidgetsApplication3()
{}obj::obj(QObject* parent)
{}

 运行效果:

(2)信号和槽的五种写法与使用方式

(3)信号和槽之间的关系:

1、信号的参数类型必须与槽函数参数的类型相对应

signals:      //声明信号void testsignal(int);public slots: //声明槽void testslot(int);emit testsignal(100);  //触发信号

2、信号的参数个数大于等于槽函数的参数个数

signals:      //声明信号void testsignal(int,int);public slots: //声明槽void testslot(int);emit testsignal(100,100);  //触发信号

3、信号和槽函数之间的关系是多对多,信号也可以 连接到另一个信号上

signals:    //声明信号void testsignal(int);
public slots: //声明槽void testslot(int);
public slots: //声明槽void testslot2(int);QObject::connect(this,&QtWidgetsApplication3::testsignal, qobj,&obj::testslot); //连接信号和槽QObject::connect(this,&QtWidgetsApplication3::testsignal, qobj,&obj::testslot2); //连接信号和槽emit testsignal(100);  //触发信号

4、信号和槽的连接机制原理:通过QObject::connect来实现的

QObject::connect(sender, &Sender::signal, receiver, &Receiver::slot);
//在上述代码中,sender对象的signal信号与receiver对象的slot槽函数被连接起来。

5、信号和槽的连接类型:

  • 直接连接(Direct Connection):这种连接方式类似于自动连接,但是即使在不同线程中也会立即调用槽函数。需要注意的是,这种方式可能导致竞态条件,因为它绕过了事件队列,所以使用时需要特别小心。
  • 队列连接(Queued Connection):在这种模式下,信号的发射不会立即导致槽函数的执行。相反,信号会被放入事件队列中,在下一个事件循环开始时才执行槽函数。这种方式常用于跨线程通信,因为可以避免直接从非GUI线程中调用可能会修改GUI组件的方法。
  • 自动连接(Auto Connection):这是默认的连接方式。当信号被发射时,Qt会立即调用相关的槽函数。这种方式适用于大多数情况,因为它是最快的方式,并且不需要额外的线程同步机制。
//直接连接
connect(button, &QPushButton::clicked, this, &MyWidget::handleClick, Qt::DirectConnection);
//队列连接
connect(button, &QPushButton::clicked, this, &MyWidget::handleClick, Qt::QueuedConnection);
//自动连接
connect(button, &QPushButton::clicked, this, &MyWidget::handleClick);

6、信号发射原理

emit mySignal(data);
//在上述代码中,当调用emit mySignal(data);时,所有连接到mySignaal的槽函数都会被调用。

7、槽函数调用过程

当一个信号被发射时,Qt负责按连接顺序调用与该信号连接的所有槽函数。

8、信号发射与线程

  • 信号可以安全地跨线程发射,如果信号接收者位于不同线程,Qt会自动将信号的处理放入目标线程的事件循环中,确保线程安全。
  • 信号的发射和槽的执行会自动适应线程间的通信机制,通过Qt的事件循环和消息队列机制来实现。
  • 线程安全:Qt的跨线程信号和槽机制是线程安全的,开发者无需担心常见的多线程问题,如竞态条件和死锁。
  • 自动同步:Qt处理所有线程间的通信细节,确保数据在线程间传递时的完整性和一致性。

7、信号和槽异步调用

当信号和槽位于不同线程时,Qt使用事件循环来实现异步调用。信号的发射将产生一个事件,该事件被放入目标线程的事件队列中。当事件循环处理到这个事件时,与之关联的槽函数被调用。

8、事件队列的角色

事件队列在信号和槽的跨线程通信中起着至关重要的作用。每个线程都有自己的事件队列和事件循环。当一个线程向另一个线程发出信号时,这个信号被封装成一个事件,然后被加入接收线程的事件队列。这确保了即使在高度并发的环境下,槽函数的执行也是线程安全的。

三、类型信息

Q_OBJECT 宏使得类可以通过 QMetaObject获取详细的运行时类型信息。这些信息包括类名、父类、信号、槽、属性等。

QtWidgetsApplication4.h

#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication4.h"
#include <QMetaObject>   //获取元对象
#include <QMetaMethod>   //信号与槽
#include <QMetaProperty> //属性
#include <QDebug>
#include <QObject>class QtWidgetsApplication4 : public QMainWindow
{Q_OBJECT
public:QtWidgetsApplication4(QWidget *parent = nullptr);~QtWidgetsApplication4();
private:Ui::QtWidgetsApplication4Class ui;
signals:void mysignal(int); //设置类的信号
private slots: void myslot(int);   //设置类的槽
private:int myProperty=false;
};

QtWidgetsApplication4.cpp

#include "QtWidgetsApplication4.h"QtWidgetsApplication4::QtWidgetsApplication4(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);//获取元对象const QMetaObject *metaObject = this->metaObject();//打印类名qDebug() << metaObject->className();//打印所有信号qDebug() << "Signals:";for (int i = 0; i < metaObject->methodCount(); i++){QMetaMethod  method = metaObject->method(i);qDebug() << method.name();}//打印所有槽qDebug() << "Slots:";for (int i = 0; i < metaObject->methodCount(); i++){QMetaMethod  method = metaObject->method(i);if (method.methodType() == QMetaMethod::Slot)qDebug() << method.name();}//打印所有属性qDebug() << "Properties:";for (int i = 0; i < metaObject->propertyCount(); i++){QMetaProperty property = metaObject->property(i);qDebug() << property.name();}
}QtWidgetsApplication4::~QtWidgetsApplication4()
{}void QtWidgetsApplication4::myslot(int)
{}

运行效果:

 四、动态设置属性

在QT中,动态属性设置的添加与修改,可以应用于数据绑定、状态管理、主题样式、事件处理等;例如:可以将 UI 控件的属性与模型数据绑定,这样当模型数据发生变化时,UI 控件的属性会自动更新。

QtWidgetsApplication5.cpp

#include "QtWidgetsApplication5.h"QtWidgetsApplication5::QtWidgetsApplication5(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);//获取当前对象的元对象const QMetaObject *metaObject = this->metaObject();//打印类名qDebug() << metaObject->className();//动态设置属性this->setProperty("dynamicProperty",QVariant(42));//动态获取属性QVariant value = this->property("dynamicProperty");qDebug() << "dynamicProperty:" << value.toInt();//检查属性是否存在QVariant checkValue =this->property("dynamicProperty");if (checkValue.isValid()) { qDebug() << "Property exists and its value is:" << checkValue.toInt(); }else { qDebug() << "Property does not exist."; }//修改属性this->setProperty("dynamicProperty", QVariant(100));//获取修改后的属性值value = this->property("dynamicProperty");qDebug() << "Modified dynamic property value:" << value.toInt();//删除属性this->setProperty("dynamicProperty",QVariant());checkValue = this->property("dynamicProperty");if (checkValue.isValid()) {qDebug() << "Property exists and its value is:" << checkValue.toInt();}else {qDebug() << "Property has been 'deleted'.";}
}QtWidgetsApplication5::~QtWidgetsApplication5()
{}

QtWidgetsApplication5.h

#pragma once#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication5.h"
#include <QMetaObject>   //获取元对象
#include <QMetaMethod>   //信号与槽
#include <QMetaProperty> //属性
#include <QDebug>class QtWidgetsApplication5 : public QMainWindow
{Q_OBJECT
public:QtWidgetsApplication5(QWidget *parent = nullptr);~QtWidgetsApplication5();
private:Ui::QtWidgetsApplication5Class ui;
};

运行效果:

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com