Qt之QMetaEnum的简单使用(含源码和注释)
文章目录
- 一、操作示例
- 二、相关内容的个人理解
- 三、相关源码
- mainwindow.h
- mainwindow.cpp
- mainwindow.ui
- 总结
一、操作示例
下方图片未QMetaEnum的部分功能操作示例;枚举名称可选择预先定义准备好的枚举,枚举基础信息、枚举属性分别指代枚举相关信息,枚举值操作为枚举字符串与对应数值之间的相互转换操作。
二、相关内容的个人理解
- 枚举名称:枚举名称获取到的数据取决于你在使用QMetaEnum获取枚举对象时使用的枚举名称,可使用在定义枚举时的枚举名称或者通过Q_FLAG修饰符修饰的枚举名称。
- 枚举作用域:当前枚举所属的类/对象,
- 是否用作标记:要使该属性生效,需要使用Q_DECLARE_FLAGS自定义关键字定义标记宏名称,然后使用Q_FLAG修饰自定义关键字,如下
// 创建类中的自定义枚举1enum 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修饰的枚举,如下
// 创建类中的自定义枚举2enum 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_OBJECTpublic:// 创建类中的自定义枚举1enum E_ClassEnumOne{eOneFirst = 1,eOneSecond = 10,eOneThird};Q_ENUM(E_ClassEnumOne) // 注册自定义枚举到元数据中,该宏只能在类中使用Q_DECLARE_FLAGS(EnumOneFlag, E_ClassEnumOne); // 使用该宏修饰后,可直接使用修饰的关键字替代对应的枚举名称使用Q_FLAG(EnumOneFlag) // 枚举作为标记的宏定义,使用该宏修饰后,可直接使用 QMetaEnum::fromType<EnumOneFlag>() 获取相应的枚举类型// 创建类中的自定义枚举2enum 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^/)
注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除