Q_ENUM
Después de personalizar una variable de enumeración, use Q_ENUM (nombre del tipo de enumeración) para registrar el metaobjeto, y luego puede obtener un objeto QMetaEnum, que puede usarse como intermediario para completar fácilmente la conversión mutua entre enumeración y cadena.
Q_FLAG
Q_ENUM puede implementar la mayoría de las funciones comunes. La introducción de Q_FLAG es principalmente para resolver el uso combinado de variables de enumeración y aumentar el cálculo AND NOR entre las variables de enumeración. Por ejemplo, Up es 1, Left es 4 y Up | Left es 5 , que es significativo. Valor.
Código
Q_ENUM toma la enumeración Log_Level como ejemplo, Q_FLAG toma la enumeración de Orientación como ejemplo:
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
enum Log_Level{
DEBUG = 5,
INFO,
WARNING,
ERROR
};
Q_ENUM(Log_Level)//注册元对象
enum Orientation{
Up = 1,
Down = 2,
Left = 4,
Right = 8
};
Q_ENUM(Orientation)
Q_DECLARE_FLAGS(OrientationFlags, Orientation)//定义一个QFlags
Q_FLAG(OrientationFlags)//注册QFlags为元对象
//Orientation和OrientationFlags都能被QMetaEnum识别并使用,只不过通常我们只关注Q_FLAG包装后的结构体
public:
explicit Widget(QWidget *parent = 0);
~Widget();
void Q_enumTest();
void Q_flagTest();
private:
Ui::Widget *ui;
};
//Q_DECLARE_OPERATORS_FOR_FLAGS(OrientationFlags)
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QMetaEnum>
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
Q_enumTest();
Q_flagTest();
}
Widget::~Widget()
{
delete ui;
}
//使用Q_ENUM注册枚举
void Widget::Q_enumTest()
{
//获取一个QMetaEnum 对象
QMetaEnum metaEnum = QMetaEnum::fromType<Log_Level>();
/** QMetaEnum说明
* index,指枚举列表的序号,从0开始,0、1、2、3..
* key,枚举值(字符串),比如此例中的INFO,返回值类型是const char*,打印出来是字符串
* const char*可以直接赋值给QString
* value,枚举值(整型),返回值类型是int,默认从0开始排序,指定值后按该值往后递增排序,打印出来是整型
*/
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<metaEnum.isFlag();//bool,是否被用作flag
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<metaEnum.isValid();//bool,枚举是否有效
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<metaEnum.key(1);//index序号对应的key,返回const char*
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<metaEnum.keyCount();//返回枚举数量
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<metaEnum.keyToValue("ERROR");//返回整型枚举值value
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<metaEnum.name();//枚举变量名
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<metaEnum.scope();//返回枚举定义所在类名
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<metaEnum.value(2);//根据index序号返回枚举整型值value
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<metaEnum.valueToKey(5);//value对应枚举名key
}
//使用Q_FLAG注册枚举,使用Q_FLAG包装后的OrientationFlags
void Widget::Q_flagTest()
{
QMetaEnum metaEnum = QMetaEnum::fromType<OrientationFlags>();
/** 经过Q_FLAG包装之后,QMetaEnum具有了操作复合枚举量的能力
* 注意这时应当使用keysToValue()和valueToKeys()函数,取代之前的keyToValue()和valueToKey()函数
* isFlag()函数返回值变成了true
* name()和enumName()分别返回Q_FLAG包装后和包装前的结构名
*/
qDebug()<< "keysToValue:"<<metaEnum.keysToValue("Up|Left");
qDebug()<< "valueToKeys:"<<metaEnum.valueToKeys(Up|Left);
qDebug()<< "isFlag:"<<metaEnum.isFlag();
qDebug()<< "name:"<<metaEnum.name();
qDebug()<< "scope:"<<metaEnum.scope()<<endl;
// qDebug()<< "enumName:"<<metaEnum.enumName(); //since Qt5.12
}
Imprimir
[ ..\EnumTest\widget.cpp ] 30 Widget::Q_enumTest false
[ ..\EnumTest\widget.cpp ] 31 Widget::Q_enumTest true
[ ..\EnumTest\widget.cpp ] 32 Widget::Q_enumTest INFO
[ ..\EnumTest\widget.cpp ] 33 Widget::Q_enumTest 4
[ ..\EnumTest\widget.cpp ] 34 Widget::Q_enumTest 8
[ ..\EnumTest\widget.cpp ] 35 Widget::Q_enumTest Log_Level
[ ..\EnumTest\widget.cpp ] 36 Widget::Q_enumTest Widget
[ ..\EnumTest\widget.cpp ] 37 Widget::Q_enumTest 7
[ ..\EnumTest\widget.cpp ] 38 Widget::Q_enumTest DEBUG
keysToValue: 5
valueToKeys: "Up|Left"
isFlag: true
name: OrientationFlags
scope: Widget