Qt中的枚举变量,Q_ENUM,Q_FLAG,Q_NAMESPACE,Q_ENUM_NS,Q_FLAG_NS以及其他
Qt QMetaEnum Class
Qt Q_ENUM(…)
Qt Q_FLAG(…)
Q_ENUM 宏注册枚举类型
QMetaEnum
QMetaEnum功能方法(QT5.12)
Qt中的枚举变量,Q_ENUM,Q_FLAG,Q_NAMESPACE,Q_ENUM_NS,Q_FLAG_NS以及其他
Qt 帮助文档说明:
注意:如果要用或结合,isFlag()
必须时true
头文件:
#include <QWidget>
#include <QDebug>
#include <QMetaEnum>
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
enum Priority {High = 1, Low = 2, VeryHigh = 4, VeryLow = 8};
Q_ENUM(Priority)
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
源文件:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowModality(Qt::ApplicationModal);
qDebug() << Priority::High << Priority::Low;
QMetaEnum metaEnum = QMetaEnum::fromType<Widget::Priority>();
int count = metaEnum.keyCount(); //4
for (int i = 0; i < count; ++i)
{
qDebug() << i << ") key: " << metaEnum.key(i) << "; value: " << metaEnum.value(i);
}
//Returns the name of the type (without the scope).
qDebug()<< "name: " << metaEnum.name();
//Returns the enum name of the flag (without the scope).
qDebug()<< "enumName: " << metaEnum.enumName();
//如果此枚举用作标志,则返回true;否则返回false; 当用作标志时,可以使用OR运算符组合枚举数
qDebug()<< "isFlag: " << metaEnum.isFlag();
//如果此枚举数声明为C++11枚举类,则返回true;否则返回false
qDebug()<< "isScoped: " << metaEnum.isScoped();
//如果此枚举有效(有名称),则返回true;否则返回false
qDebug()<< "isValid: " << metaEnum.isValid();
qDebug()<< "keyCount: " << metaEnum.keyCount(); //返回键个数
//返回具有给定索引的键,如果不存在这样的键,则返回0。 "VeryHigh"
qDebug()<< "key(2): " << metaEnum.key(2);
//返回给定枚举键的整数值,如果未定义键,则返回-1
qDebug()<< "keyToValue(\"High\"): " << metaEnum.keyToValue("High");
//返回使用OR运算符组合键的值,如果未定义键,则返回-1
//请注意,键中的字符串必须以“|”分隔; 需要 isFlag 为 true
qDebug()<< "keysToValue(\"High|VeryHigh\"): " << metaEnum.keysToValue("High|VeryHigh");
//返回此枚举数在其中声明的范围。即所属类/namespace的名字 MainWindow
qDebug()<< "scope: " << metaEnum.scope();
qDebug()<< "value(0): " << metaEnum.value(0); //参数为索引值,返回索引对应的 value
qDebug()<< "value(1): " << metaEnum.value(1);
qDebug()<< "value(2): " << metaEnum.value(2);
qDebug()<< "value(3): " << metaEnum.value(3);
qDebug()<< "value(4): " << metaEnum.value(4); //索引超范围,返回-1。
//参数为 value,返回对应的 key Low
qDebug()<< "valueToKey(2): " << metaEnum.valueToKey(Priority::Low);
//用 | 结合,isFlag() 必须是 true,返回表示给定值的由“|”分隔键组成的字节数组。"Low|VeryHigh"
qDebug()<< "valueToKeys(1|2): " << metaEnum.valueToKeys(Priority::High|Priority::Low);
}
输出为:
- 尽管定义的枚举值分别为 1, 2, 4, 8,可以用或运算组合,但仍不是 flag,
isFlag
为false
。 const char *QMetaEnum::key(int index) const
,中的参数为索引,索引不是键值,根据枚举声明时的顺序,第一个为 0,依次递增,因此key(2)
为VeryHigh
;返回的为枚举的名字,而不是枚举的整数值。int QMetaEnum::keyToValue(const char *key, bool *ok = nullptr) const
,参数为枚举名字,如High
,返回的是该键的整型数值。int QMetaEnum::value(int index) const
函数参数为索引,返回整型键值。keysToValue
和valueToKeys
需要isFalg
为true
。
让枚举能作为 flag 使用
头文件做如下改变:
```cpp
#include <QWidget>
#include <QDebug>
#include <QMetaEnum>
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
enum Priority {High = 1, Low = 2, VeryHigh = 4, VeryLow = 8};
Q_DECLARE_FLAGS(Priorities, Priority)
Q_FLAG(Priority)
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
Q_DECLARE_OPERATORS_FOR_FLAGS(Widget::Priorities)
其中 Q_DECLARE_FLAGS(Flags, Enum)
宏定义为 typedef QFlags<Enum> Flags;
源文件不变,但输出结果改变:
这是 isFlag
才为 true
。
注意这里不用 Q_ENUM()
宏。
metaEnum.valueToKeys(1|2)
也可以写为 metaEnum.valueToKeys(Priority::High|Priority::Low)
作为标志位使用,利用或运算检查是否存在某个标志位:
Widget::Priorities flag;
flag.setFlag(Priority::Low);
qDebug() << "flag: " << flag;
auto testFlag = [](Widget::Priorities flag){
if (flag.testFlag(Priority::Low))
qDebug() << "flag Priority::Low is set";
if (flag.testFlag(Priority::High))
qDebug() << "flag Priority::High is set";
if (flag.testFlag(Priority::VeryLow))
qDebug() << "flag Priority::VeryLow is set";
if (flag.testFlag(Priority::VeryHigh))
qDebug() << "flag Priority::VeryHigh is set";
};
testFlag(Priority::Low | Priority::VeryLow);
输出:
flag: QFlags<Widget::Priority>(Low)
flag Priority::Low is set
flag Priority::VeryLow is set