Qt之QMetaEnum的简单使用(含源码和注释)

发布于:2025-08-13 ⋅ 阅读:(15) ⋅ 点赞:(0)

一、操作示例

下方图片未QMetaEnum的部分功能操作示例;枚举名称可选择预先定义准备好的枚举,枚举基础信息枚举属性分别指代枚举相关信息,枚举值操作为枚举字符串与对应数值之间的相互转换操作。
在这里插入图片描述

二、相关内容的个人理解

  1. 枚举名称:枚举名称获取到的数据取决于你在使用QMetaEnum获取枚举对象时使用的枚举名称,可使用在定义枚举时的枚举名称或者通过Q_FLAG修饰符修饰的枚举名称。
  2. 枚举作用域:当前枚举所属的类/对象,
  3. 是否用作标记:要使该属性生效,需要使用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);
	
  1. 是否有效:如果此枚举有效(有名称),则返回true;否则返回false。
  2. 是否声明为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^/)

注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除


网站公告

今日签到

点亮在社区的每一天
去签到