如何将枚举转换为QString?

47
我尝试使用Qt反射将枚举转换为QString。下面是代码的一部分:
class ModelApple
{
    Q_GADGET
    Q_ENUMS(AppleType)
public:
    enum AppleType {
      Big,
      Small
    }
}

这是我尝试做的事情:

convertEnumToQString(ModelApple::Big)

返回"Big"

这个可能吗? 如果你对convertEnumToQString有任何想法,请分享它

6个回答

79
你需要使用Q_ENUM宏,该宏将枚举类型注册到元对象系统中。
enum AppleType {
  Big,
  Small
};
Q_ENUM(AppleType)

现在你可以使用QMetaEnum类来访问有关枚举器的元数据。
QMetaEnum metaEnum = QMetaEnum::fromType<ModelApple::AppleType>();
qDebug() << metaEnum.valueToKey(ModelApple::Big);

以下是这种实用程序的通用模板:

template<typename QEnum>
std::string QtEnumToString (const QEnum value)
{
  return std::string(QMetaEnum::fromType<QEnum>().valueToKey(value));
}

8
QMetaEnum::fromType<T> 函数在Qt 5中可用,而在Qt 4中不存在。建议加上这个说明。另外,我不建议使用QMetaEnum::key函数,因为它需要index作为参数,而enum AppleType { Big = 2, Small}是如何声明的呢? - Danh
4
从文档中看,似乎这只在Qt 5.5及以上版本中可用,因此我仍需要使用我所提供的答案中的方法(本来打算更新我的代码,但现在必须使用Qt 5.4)。 - CJCombrink
'keyToValue()'可以反过来做:从字符串获取枚举值! - jaques-sam
我得到了这个错误信息:undefined reference to MyClass::staticMetaObject。我从Q_ENUM的官方页面复制了示例代码。 - SuB

41

找到了一个更加优雅的方法(Qt 5.9),只需一行代码,借助强大的QVariant。

将枚举转换为字符串:

QString theBig = QVariant::fromValue(ModelApple::Big).toString();

也许您不再需要QMetaEnum。

示例代码如下:

ModelApple(无需声明Q_DECLARE_METATYPE)

class ModelApple : public QObject
{
    Q_OBJECT
public:
    enum AppleType {
      Big,
      Small
    };
    Q_ENUM(AppleType)
    explicit ModelApple(QObject *parent = nullptr);
};

我创建了一个小部件应用程序,在其中调用QVariant功能:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <modelapple.h>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QString s = QVariant::fromValue(ModelApple::Big).toString();
    qDebug() << s;

}

MainWindow::~MainWindow()
{
    delete ui;
}

你可以看到我尝试在控制台输出字符串,它确实成功了: 在这里输入图片描述

很抱歉我之前使用了反向转换,我在一些项目中已经成功使用过,但是这次我遇到了编译错误。所以我决定从我的答案中将其删除。


1
感谢您的回答,看起来这个方法需要添加 Q_DECLARE_METATYPE(ModelApple::AppleType),即使添加了也能成功编译,但结果是一个空字符串。您能否提供此代码的示例? - JustWe
对于那些在解决方案上遇到困难的人:你需要 Q_OBJECT 和 Q_ENUM。此外,你的枚举必须是公共的。 - Cheesi
1
@Cheesi,你不需要使用Q_OBJECT:除非你真的在创建一个QObject,否则Q_GADGET就足够了。 - Ruslan

9
以下内容可以帮助您入门:

以下应该可以帮助您入门:

QString convertEnumToQString(ModelApple::AppleType type) {
    const QMetaObject metaObject = ModelApple::staticMetaObject;
    int enumIndex = metaObject.indexOfEnumerator("AppleType");
    if(enumIndex == -1) {
        /* The enum does not contain the specified enum */
        return "";
    }
    QMetaEnum en = metaObject.enumerator(enumIndex);
    return QString(en.valueToKey(type));
}

为什么不将 enumStringenumString = en.valueToKey(type); 的声明合并在一起呢?这样只调用一个构造函数而不是一个构造函数和一个 operator =。此外,我们可以消除对 -1 的检查,因为我们可以确定该枚举已存在。 - Danh
那我需要指定枚举类型“AppleType”吗? - JustWe
@Danh 是的,你可以这样做。我的实际代码是一个模板函数,它接受枚举名称和枚举值以返回字符串。我修改了它来回答这个问题。我的用法是 string = convertEnumToQString<ModelApple>("AppleType", ModelApple::Big); 所以我需要检查有效的枚举并在调试时断言。同时,在返回之前进行断言,因此首先进行赋值然后返回(纯粹为了调试)。 - CJCombrink
1
我理解了模板的用法。关于声明、赋值和返回,我仍然认为我们不应该多此一举。 - Danh
很不幸,除非您有Qt 5.5(那么您可以使用其他答案),否则是的,这就是为什么我建议添加检查以防将来决定更改枚举名称。 - CJCombrink
好的,不幸的是我正在使用Qt 5.3。谢谢大家。 - JustWe

8

对于全局枚举声明,在任何头文件中使用以下内容:

namespace YourNamespace {

Q_NAMESPACE

enum YourEnum: int {

    EnumValue1,
    EnumValue2
};
Q_ENUM_NS(YourEnum)

}

这是你想获取枚举描述的地方:

QMetaEnum metaEnum = QMetaEnum::fromType<YourEnum>();
qDebug() << "Enum description: " << metaEnum.name() << "::" << metaEnum.valueToKey(YourEnum::EnumValue2);

1
我多年来一直尝试让它工作,最近我尝试了你的解决方案,并且成功了!诀窍是将我的“全局”枚举(即:不包含在类中)包装在命名空间中。谢谢! - Doug
1
非常有帮助的答案。谢谢! - developer01

2
如何考虑:
QString convertEnumToQString(ModelApple::AppleType type)
{
    const QMetaObject &mo = ModelApple::staticMetaObject;
    int index = mo.indexOfEnumerator("AppleType");
    QMetaEnum metaEnum = mo.enumerator(index);
    return metaEnum.valueToKey(type);
}

UPDATED: For Qt 5.5, see this answer


2

我曾经遇到了同样的问题,以下是我的解决方法。这里特别针对 Qt 4.8

QString string = enumToString(ModelApple::Big);

QString ModelApple::enumToString(AppleType apple)
{
    int index = metaObject()->indexOfEnumerator("AppleType");
    QMetaEnum metaEnum = metaObject()->enumerator(index);
    return metaEnum.valueToKey(apple);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接