Q_INVOKABLE使用及Qt反射讲解
前言
这篇博文是我在搜索Q_INVOKABLE的时候发现的,个人觉得讲的不错。我自己也测试了一下Q_INVOKABLE的使用,最简单的就是可以通过一个函数的字符串直接调用函数,有点像设计模式的简单工厂模式。Q_INVOKABLE还有就是在QML中有妙用。
正文如下
Qt的元对象系统除了提供信号/槽机制的特性之外,它还提供了以下特性:
QObject::metaObject() | 返回关联的元对象 |
QMetaObject::className() | 在运行时状态下返回类名 |
QObject::inherits() | 判断类的继承关系 |
QObject::tr(),QObject::trUtf8() | 提供国际化,翻译字符串 |
QObject::setProperty(),QObject::property() | 通过名称来动态设置和获取属性 |
QMetaObject::newInstance() | 创建新实例 |
通过QObject::metaObject()方法, 所有继承于QObject的类可以 返回元对象系统为其生成的metaObject对象。QMetaObject提供的一些重要信息:
QMetaClassInfo | 通过宏Q_CLASSINFO的支持,提供类的附加信息 |
QMetaEnum | Qt特色的枚举对象,支持key和 value之间的互转 |
QMetaMethod | 提供类成员函数的元数据 |
QMetaProperty | 提供类成员属性的元数据 |
Qt反射前期准备
1、首先得继承于Q_Object,同时需要在class中加入Q_OBJECT。
2、注册类成员变量需要使用Q_PROPERTY
Q_PROPERTY( type member READ get WRITE set) 其中READ,WRITE是关键字
Type表示成员的类型(不支持自定义类型,对Qt很多基本类型都支持);
Member代表你给该成员另外起的名字,可以和变量名不同;get,set就是自己在C++函数里面定义的基本的访问函数名,不需要写参数。
3、注册类成员函数
如果你希望这个函数能够被反射,那么很简单,只需要在类的函数声明前加入Q_INVOKABLE关键字。
下面是一个例子:
//声明一个继承于QObject的类
class ReflectionObject : public QObject
{
Q_OBJECT
Q_PROPERTY(int Id READ Id WRITE setId)
Q_PROPERTY(QString Name READ Name WRITE setName)
Q_PROPERTY(QString Address READ Address WRITE setAddress)
Q_PROPERTY(PriorityType Priority READ Priority WRITE setPriority)
Q_ENUMS(PriorityType)
public:
enum PriorityType {High,Low,VeryHigh,VeryLow};
Q_INVOKABLE int Id() {return m_Id; }
Q_INVOKABLE QString Name() { return m_Name; }
Q_INVOKABLE QString Address() { return m_Address; }
Q_INVOKABLE PriorityType Priority() const {return m_Priority; }
Q_INVOKABLE void setId(const int & id) {m_Id = id; }
Q_INVOKABLE void setName(const QString & name) {m_Name = name; }
Q_INVOKABLE void setAddress(const QString & address) {m_Address = address; }
Q_INVOKABLE void setPriority(PriorityType priority) {m_Priority = priority; }
private:
int m_Id;
QString m_Name;
QString m_Address;
PriorityType m_Priority;
};
遍历该类的成员函数:
ReflectionObject theObject;
const QMetaObject* theMetaObject =theObject.metaObject();
int methodIndex;
int methodCount = theMetaObject->methodCount();
for(methodIndex = 0; methodIndex < methodCount; ++methodIndex)
{
QMetaMethod oneMethod =theMetaObject->method(methodIndex);
qDebug() <<"typeName: " <<oneMethod.typeName();
qDebug() <<"signature: " <<oneMethod.signature();
qDebug() <<"methodType: " <<oneMethod.methodType();;
qDebug() <<"parameterNames: " <<oneMethod.parameterNames() <<"\n";
}
其中typeName代表返回类型,signature只的是函数的原貌,methodType代表函数的类型,在Qt中分为三类(槽,信号,普通函数),parameterNames代表函数参数
遍历该类的成员变量:
int propertyIndex;
int propertyCount = theMetaObject->propertyCount();
for(propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
{
QMetaProperty oneProperty =theMetaObject->property(propertyIndex);
qDebug() <<"name: " << oneProperty.name();
qDebug() <<"type: " <<oneProperty.type() <<"\n";
}
int enumeratorIndex;
int enumeratorCount = theMetaObject->enumeratorCount();
for(enumeratorIndex = 0; enumeratorIndex < enumeratorCount; ++enumeratorIndex)
{
QMetaEnum oneEnumerator =theMetaObject->enumerator(enumeratorIndex);
int enumIndex;
int enumCount = oneEnumerator.keyCount();
for(enumIndex = 0;enumIndex < enumCount; ++enumIndex)
{
qDebug() <<oneEnumerator.key(enumIndex) <<" ==> " <<oneEnumerator.value(enumIndex);
}
}
这里我们看到QMetaEnum存在key、value配对出现,这必然可以互转,而QMetaEnum确实提供了方式:valueToKey()、keyToValue()。
反射的应用
反射反射,就我目前的认知水平来看,通过使用字符串,来实现函数的通用化调用,例如你可以利用反射把很多函数放置到数组中,实现一次遍历,全部调用。
目前见到的大多是利用反射来操作数据库,例如hibernate,其实可以利用Qt的反射,快速实现所谓的hibernate。
Q_INVOKABLE简单测试
reflectdatatest.h文件
#ifndef REFLECTDATATEST_H
#define REFLECTDATATEST_H
#include <QObject>
#include <QDebug>
class ReflectDataTest : public QObject
{
Q_OBJECT
public:
explicit ReflectDataTest(QObject *parent = nullptr);
Q_INVOKABLE void printTest()
{
qDebug() << __FUNCTION__ << __LINE__ << " : Q_INVOKABLE test";
}
};
#endif // REFLECTDATATEST_H
reflectdatatest.cpp文件
#include "reflectdatatest.h"
ReflectDataTest::ReflectDataTest(QObject *parent) : QObject(parent)
{
}
main.cpp调用
#include "mainwindow.h"
#include <QApplication>
#include <QMetaObject>
#include "reflectdatatest.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// MainWindow w;
// w.show();
ReflectDataTest r;
QMetaObject::invokeMethod(&r, "printTest");
return a.exec();
}
测试结果输出
ReflectDataTest::printTest 16 : Q_INVOKABLE test
原文地址(侵删)
https://www.cnblogs.com/RainyBear/p/5251440.html
版权声明:
作者:小何
链接:https://ligo100.cn/houduanjishu/qt/94.html
来源:小何博客
文章版权归作者所有,未经允许请勿转载。

共有 0 条评论