一、操作示例
下方图片未QMetaEnum的部分功能操作示例;枚举名称可选择预先定义准备好的枚举,枚举基础信息、枚举属性分别指代枚举相关信息,枚举值操作为枚举字符串与对应数值之间的相互转换操作。
二、相关内容的个人理解
- 枚举名称:枚举名称获取到的数据取决于你在使用QMetaEnum获取枚举对象时使用的枚举名称,可使用在定义枚举时的枚举名称或者通过Q_FLAG修饰符修饰的枚举名称。
- 枚举作用域:当前枚举所属的类/对象,
- 是否用作标记:要使该属性生效,需要使用Q_DECLARE_FLAGS自定义关键字定义标记宏名称,然后使用Q_FLAG修饰自定义关键字,如下
// 创建类中的自定义枚举1
enum E_ClassEnumOne
{
eOneFirst = 1,
eOneSecond = 10,
eOneThird
};
Q_ENUM(E_ClassEnumOne) // 注册自定义枚举到元数据中,该宏只能在类中使用
Q_DECLARE_FLAGS(EnumOneFlag, E_ClassEnumOne); // 使用该宏修饰后,可直接使用修饰的关键字替代对应的枚举名称使用
Q_FLAG(EnumOneFlag) // 枚举作为标记的宏定义,使用该宏修饰后,可直接使用 QMetaEnum::fromType<EnumOneFlag>() 获取相应的枚举类型
// 标记使用实例
// Q_DECLARE_FLAGS通过定义的Flag类型
EnumOneFlag oneFlag;
// 设置一个默认属性
oneFlag.setFlag(eOneSecond);
// 分别测试一个已设置和未设置的属性状态
qDebug() << oneFlag.testFlag(eOneSecond);
qDebug() << oneFlag.testFlag(eOneFirst);
- 是否有效:如果此枚举有效(有名称),则返回true;否则返回false。
- 是否声明为C++11枚举类:C++11枚举类是指,使用class修饰的枚举,如下
// 创建类中的自定义枚举2
enum class E_ClassEnumTwo
{
eTwoFirst = 2,
eTwoSecond,
eTwoThird,
eTwoFourth = 40,
eTwoFifth,
};
三、相关源码
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMetaEnum>
#include <QDebug>
#include <QAbstractItemModel>
// 创全局的自定义枚举
enum E_GlobalEnum
{
eGlobalFirst = 2,
eGlobalSecond,
eGlobalThird
};
Q_DECLARE_FLAGS(EnumGlobalFlag, E_GlobalEnum);
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
// 创建类中的自定义枚举1
enum E_ClassEnumOne
{
eOneFirst = 1,
eOneSecond = 10,
eOneThird
};
Q_ENUM(E_ClassEnumOne) // 注册自定义枚举到元数据中,该宏只能在类中使用
Q_DECLARE_FLAGS(EnumOneFlag, E_ClassEnumOne); // 使用该宏修饰后,可直接使用修饰的关键字替代对应的枚举名称使用
Q_FLAG(EnumOneFlag) // 枚举作为标记的宏定义,使用该宏修饰后,可直接使用 QMetaEnum::fromType<EnumOneFlag>() 获取相应的枚举类型
// 创建类中的自定义枚举2
enum class E_ClassEnumTwo
{
eTwoFirst = 2,
eTwoSecond,
eTwoThird,
eTwoFourth = 40,
eTwoFifth,
};
Q_ENUM(E_ClassEnumTwo) // 注册自定义枚举到元数据中,该宏只能在类中使用
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
/**
* @brief initMetaEnumMap 初始化枚举元数据容器
*/
void initMetaEnumMap();
/**
* @brief clearWidgetVal 清空控件值
*/
void clearWidgetVal();
/**
* @brief enumFlagsTest 自定义枚举Flag对象的测试
*/
void enumFlagsTest();
private slots:
/**
* @brief on_comboBoxCurEnum_currentIndexChanged 枚举切换下拉框
* @param arg1 当前下拉框
*/
void on_comboBoxCurEnum_currentIndexChanged(const QString &arg1);
/**
* @brief on_pushButtonStrToVal_clicked 字符串转数值
*/
void on_pushButtonStrToVal_clicked();
/**
* @brief on_pushButtonValToStr_clicked 数值转字符串
*/
void on_pushButtonValToStr_clicked();
private:
Ui::MainWindow *ui;
QMap<QString, QMetaEnum> m_mapMetaEnum; // 存储枚举元数据
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMetaEnum>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
initMetaEnumMap();
// 枚举标记测试函数
enumFlagsTest();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::initMetaEnumMap()
{
// 该行构建报错
// m_mapMetaEnum["E_GlobalEnum"] = QMetaEnum::fromType<E_GlobalEnum>();
m_mapMetaEnum["EnumOneFlag"] = QMetaEnum::fromType<EnumOneFlag>();
m_mapMetaEnum["E_ClassEnumOne"] = QMetaEnum::fromType<E_ClassEnumOne>();
m_mapMetaEnum["E_ClassEnumTwo"] = QMetaEnum::fromType<E_ClassEnumTwo>();
}
void MainWindow::clearWidgetVal()
{
// 清空文本框
auto listEidt = findChildren<QLineEdit *>();
foreach(auto e, listEidt) {
e->setText("");
}
// 清空复选框
auto listCheck = findChildren<QCheckBox *>();
foreach(auto c, listCheck) {
c->setChecked(false);
}
// 清空下拉框
auto listCombo = findChildren<QComboBox *>();
listCombo.removeOne(ui->comboBoxCurEnum);
foreach(auto c, listCombo) {
c->clear();
}
// 清空枚举值信息框
ui->textBrowserVal->clear();
}
void MainWindow::enumFlagsTest()
{
// Q_DECLARE_FLAGS通过定义的Flag类型
EnumOneFlag oneFlag;
// 设置一个默认属性
oneFlag.setFlag(eOneSecond);
// 分别测试一个已设置和未设置的属性状态
qDebug() << oneFlag.testFlag(eOneSecond);
qDebug() << oneFlag.testFlag(eOneFirst);
// Q_DECLARE_FLAGS宏内部为通过typedef关键字的自定义类型
QFlags<E_ClassEnumTwo> twoFlag;
// 设置一个默认属性
twoFlag.setFlag(E_ClassEnumTwo::eTwoFirst, true);
qDebug() << twoFlag.testFlag(E_ClassEnumTwo::eTwoFifth);
EnumGlobalFlag globalFlag;
// 首先输出当前属性是否存在
qDebug() << globalFlag.testFlag(eGlobalFirst);
// 添加当前属性后再次输出相关属性状态
globalFlag.setFlag(eGlobalFirst);
qDebug() << globalFlag.testFlag(eGlobalFirst);
}
void MainWindow::on_comboBoxCurEnum_currentIndexChanged(const QString &arg1)
{
// 清空控件值
clearWidgetVal();
// 当枚举对象容器不存在当前类型时返回
if(!m_mapMetaEnum.contains(arg1)) {
return;
}
const QMetaEnum &metaEnum = m_mapMetaEnum[arg1];
// 获取枚举名称
ui->lineEditName->setText(QString(u8"enumName: %1 name: %2").arg(metaEnum.enumName(), metaEnum.name()));
// 获取枚举名称
ui->lineEditKeyCount->setText(QString::number(metaEnum.keyCount()));
// 返回枚举的作用域
ui->lineEditScope->setText(metaEnum.scope());
// 是否用作标记
ui->checkBoxFlag->setChecked(metaEnum.isFlag());
// 是否有效
ui->checkBoxValid->setChecked(metaEnum.isValid());
// 是否声明为c++11枚举类
ui->checkBoxScoped->setChecked(metaEnum.isScoped());
// 根据获取的枚举对象,遍历当前对象的所有值并添加到下拉框中
for(int idx = 0; idx < metaEnum.keyCount(); ++idx) {
ui->textBrowserVal->append(QString(u8"枚举值文本:%1 枚举值:%2").arg(metaEnum.key(idx)).arg(metaEnum.value(idx)));
ui->comboBoxStrToVal->addItem(metaEnum.key(idx));
ui->comboBoxValToStr->addItem(QString::number(metaEnum.value(idx)));
}
}
void MainWindow::on_pushButtonStrToVal_clicked()
{
// 当枚举对象容器不存在当前类型时返回
if(!m_mapMetaEnum.contains(ui->comboBoxCurEnum->currentText())) {
return;
}
// 获取当前枚举对象
const QMetaEnum &metaEnum = m_mapMetaEnum[ui->comboBoxCurEnum->currentText()];
// 获取当前文本转换
QString keyStr = ui->comboBoxStrToVal->currentText();
bool isOk = false;
int val = metaEnum.keyToValue(keyStr.toStdString().data(), &isOk);
// 转换成功添加到输出框中
if(isOk) {
ui->textBrowserOutPut->append(QString(u8"字符串 %1 转 值 %2").arg(keyStr).arg(val));
}
}
void MainWindow::on_pushButtonValToStr_clicked()
{
// 当枚举对象容器不存在当前类型时返回
if(!m_mapMetaEnum.contains(ui->comboBoxCurEnum->currentText())) {
return;
}
// 获取当前枚举对象
const QMetaEnum &metaEnum = m_mapMetaEnum[ui->comboBoxCurEnum->currentText()];
// 获取当前值并转换
int val = ui->comboBoxValToStr->currentText().toInt();
QString keyStr = metaEnum.valueToKey(val);
ui->textBrowserOutPut->append(QString(u8"值 %1 转 字符串 %2").arg(val).arg(keyStr));
}
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>564</width>
<height>671</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5" stretch="0,1">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>枚举名称</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxCurEnum">
<item>
<property name="text">
<string/>
</property>
</item>
<item>
<property name="text">
<string>E_GlobalEnum</string>
</property>
</item>
<item>
<property name="text">
<string>EnumOneFlag</string>
</property>
</item>
<item>
<property name="text">
<string>E_ClassEnumOne</string>
</property>
</item>
<item>
<property name="text">
<string>E_ClassEnumTwo</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>枚举基础信息</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>枚举名称 </string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditName">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>枚举值数量</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditKeyCount">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>枚举作用域</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditScope">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>枚举值列表</string>
</property>
</widget>
</item>
<item>
<widget class="QTextBrowser" name="textBrowserVal"/>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>枚举属性</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="checkBoxFlag">
<property name="text">
<string>是否用作标记</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxValid">
<property name="text">
<string>是否有效</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxScoped">
<property name="text">
<string>是否声明为c++11枚举类</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>枚举值操作</string>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="1,0" columnminimumwidth="0,0">
<item row="1" column="0">
<widget class="QComboBox" name="comboBoxValToStr"/>
</item>
<item row="0" column="0">
<widget class="QComboBox" name="comboBoxStrToVal"/>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButtonValToStr">
<property name="text">
<string>数值转字符串</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pushButtonStrToVal">
<property name="text">
<string>字符串转数值</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QTextBrowser" name="textBrowserOutPut"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>564</width>
<height>26</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
总结
QMetaEnum类我主要使用文本转枚举值、枚举值转枚举文本的功能,使用改内容可实现在项目中,如遇到多个字符串判断,可使用该字符串转换为枚举值,转if为switch的判断方法。
友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 ^o^/)
注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除