我们常常想 知道 枚举类型 如何输出对应的英文 而不是数字呢?
QT为我们提供了QMetaEnum类 解决了 这样的需求
返回定义的枚举的名称: enumName()
是否作为标志: isFlag()
是否作为c++11枚举 isScoped()
枚举是否有效 isValid()
返回枚举数量:keyCount()
返回index序号对应的key key()
根据index序号返回枚举整型值value value()
枚举变量名 name()
返回枚举定义所在类名 scope()
返回整型枚举值value keyToValue
返回value对应枚举名key valueToKey
什么是c++11的枚举,和普通枚举有什么不一样,怎么写的呢
c++11写法:
enum class Day
{
ONE,
TWO,
THREE,
FOUR,
FIVE
};
c++普通写法:
enum Day
{
ONE,
TWO,
THREE,
FOUR,
FIVE
};
使用QMetaEnum 必须要有Q_OBJECT宏 还有Q_ENUM()或者Q_FLAG()
#pragma once
#include
#include "ui_QMetaEnumTest.h"
#include
#include
class QMetaEnumTest : public QWidget
{
Q_OBJECT
public:
enum class NUMBER
{
ONE,
TWO,
THREE,
FOUR,
FIVE
};
Q_ENUM(NUMBER) //注册枚举
enum Orientation
{
Up = 1,
Down = 2,
Left = 4,
Right = 8,
};
Q_DECLARE_FLAGS(OrientationFlags, Orientation) // 相当于 QFlags OrientationFlags;
Q_FLAG(OrientationFlags) //将OrientationFlags 注册为元对象
public:
QMetaEnumTest(QWidget *parent = Q_NULLPTR);
void enumTest();
void flagTest();
private:
Ui::QMetaEnumTestClass ui;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaEnumTest::OrientationFlags)
#include "QMetaEnumTest.h"
QMetaEnumTest::QMetaEnumTest(QWidget* parent)
: QWidget(parent)
{
ui.setupUi(this);
enumTest();
flagTest();
}
void QMetaEnumTest::enumTest()
{
QMetaEnum metaEnum = QMetaEnum::fromType<NUMBER>();
qDebug() << "[" << "file:" << __FILE__ << "line:" << __LINE__ << "]" << "enumName() :" << metaEnum.enumName();
qDebug() << "[" << "file:" << __FILE__ << "line:" << __LINE__ << "]" << "isFlag() :" << metaEnum.isFlag();
qDebug() << "[" << "file:" << __FILE__ << "line:" << __LINE__ << "]" << "isScoped():" << metaEnum.isScoped();
qDebug() << "[" << "file:" << __FILE__ << "line:" << __LINE__ << "]" << "isValid() :" << metaEnum.isValid();
qDebug() << "[" << "file:" << __FILE__ << "line:" << __LINE__ << "]" << "key(0) :" << metaEnum.key(0);
qDebug() << "[" << "file:" << __FILE__ << "line:" << __LINE__ << "]" << "keyCount() :" << metaEnum.keyCount();
qDebug() << "[" << "file:" << __FILE__ << "line:" << __LINE__ << "]" << "keyToValue() :" << metaEnum.keyToValue("THREE");
qDebug() << "[" << "file:" << __FILE__ << "line:" << __LINE__ << "]" << "name() :" << metaEnum.name();
qDebug() << "[" << "file:" << __FILE__ << "line:" << __LINE__ << "]" << "scope() :" << metaEnum.scope();
qDebug() << "[" << "file:" << __FILE__ << "line:" << __LINE__ << "]" << "value() :" << metaEnum.value(1);
qDebug() << "[" << "file:" << __FILE__ << "line:" << __LINE__ << "]" << "valueToKey() :" << metaEnum.valueToKey(0);
}
void QMetaEnumTest::flagTest()
{
qDebug() << (Up |Down);
//注意这里不是 Orientation,因为 我们没有用Q_ENUM来注册枚举 我们需要写包装后的枚举类型
QMetaEnum metaEnum = QMetaEnum::fromType<OrientationFlags>();
//我们使用keyToValue 和 valueToKey 不生效 因为这是复合类型 这个是没有经过重载的
qDebug() << "keyToValue:" << metaEnum.keyToValue("Up|Down");
qDebug() << "valueToKey:" << metaEnum.valueToKey(Up | Down);
//我们需要使用keysToValue 和 valueToKeys 才生效
//经过Q_FLAG包装之后,QMetaEnum具有了操作复合枚举量的能力,所以
qDebug() << "keysToValue:" << metaEnum.keysToValue("Up|Down");
qDebug() << "valueToKeys:" << metaEnum.valueToKeys(Up | Down);
qDebug() << "isFlag:" << metaEnum.isFlag();
//包装后的类型
qDebug() << "name:" << metaEnum.name();
//包装前的类型
qDebug() << "enumName:" << metaEnum.enumName();
qDebug() << "scope:" << metaEnum.scope() << endl;
}
运行结果:
Q_ENUM()下:
Q_DECLARE_FLAGS(Flags, Enum) 实际上被展开成typedef QFlags< Enum > Flags
Q_DECLARE_FLAGS实际上是QFlags的定义式,之后才能使用Q_FLAG(Flags)把定义的Flags注册到元对象系统
Q_DECLARE_FLAGS(Flags, Enum)宏将普通结构体Enum重新定义成了一个可以自由进行与或非操作的安全的结构体Flags。
当我们在类的结尾写上Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaEnumTest::OrientationFlags)
如果不加该宏:
我们发现 打印的第一个,不一样,此时我们就可以看出这个宏的作用:
Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)赋予了Flags一个全局操作符“|”,没有这个宏语句,Flags之间进行与操作后的结果将是一个int值,而不是Flags值。Q_DECLARE_OPERATORS_FOR_FLAGS应当定义在类外;
参考博客:
Q_ENUM,Q_FLAG,Q_NAMESPACE,Q_ENUM_NS,Q_FLAG_NS介绍
QT QMetaEnum类