Любое значение типа Qt::Alignment (флаг) можно преобразовать в удобную для чтения строку, как показано ниже:
QString s = QVariant::fromValue<Qt::Alignment>(Qt::AlignTop | Qt::AlignLeft).toString();
Этот код заполняет sAlignLeading|AlignTop.
В некотором смысле это правильно, поскольку Qt::AlignLeading является синонимом Qt::AlignLeft. Я бы предпочел получить исходное значение, а не его синоним, хотя, по-видимому, команда Qt согласна, поскольку редактор свойств дизайнера Qt не упоминает синонимы.
Есть ли способ получить нужную мне строку с помощью функций только Qt, т.е. без какого-либо взлома?
Это не похоже на правду. Можно объявить флаги, для которых QVariant::toString возвращает пустую строку и в то же время QMetaEnum::valueToKeys() возвращает правильные данные.
Извините за путаницу. Я имел в виду valueToKey() (см. код qvariant.cpp, он никогда не использует функцию «ключи»). Именно по этой причине он возвращает нулевую строку: он возвращает только один известный ключ для определенного перечисления, если оно существует, поэтому перечисления с ИЛИ не будут учитываться, если они не определены (например: Qt.AlignCenter). Тем не менее, если проблема заключается в отображении значения в представлении элемента, самым простым решением было бы просто переопределить displayText() в делегате.
@musicamante Возможно, вы захотите взглянуть на принятый ответ.





Чтобы понять проблему, следует посмотреть файл qnamespace.h. Чтобы воспроизвести проблему Alignment, вам необходимо дополнительно объявить макросы
Q_DECLARE_OPERATORS_FOR_FLAGS(TestEnums)
Пример для пространств имен:
QT_BEGIN_NAMESPACE
namespace Test {
Q_NAMESPACE_EXPORT(Q_CORE_EXPORT)
enum TestEnum { a = 1, b = 2, c = 4, d = 8, e = 16, f = 32 };
Q_DECLARE_FLAGS(TestEnums, TestEnum)
Q_DECLARE_OPERATORS_FOR_FLAGS(TestEnums)
// Q_ENUM_NS(TestEnum) <<NOT NEED
Q_FLAG_NS(TestEnums)
}; // namespace Test
QT_END_NAMESPACE
Обратите внимание, что макросы Q_ENUM(_NS) будут отображать только "" (для пространств имен требуется _NS).
Макрос Q_DECLARE_OPERATORS_FOR_FLAGS объявляет глобальный оператор|() для флагов. Эти макросы должны находиться в пространстве имен, но вне класса.
Пример для классов:
class Tesclass : public QObject {
Q_OBJECT
public:
Tesclass(QWidget *parent = nullptr) {}
enum TestEnum { a = 1, b = 2, c = 4, d = 8, e = 16, f = 32 };
Q_DECLARE_FLAGS(TestEnums, TestEnum)
Q_FLAG(TestEnums)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Tesclass::TestEnums)
Более подробную информацию см. также QFlags
Фрагмент, который я создал при редактировании вопроса, к которому вы, похоже, обращаетесь, был предназначен только для того, чтобы доказать, что QVariant::toString не использовался QMetaEnum::valueToKeys. Это не тот вопрос, на который я пытался получить ответ. Я описывал синонимы внутри перечисления и строку, которую мы можем сгенерировать из QVariant::toString.
Кстати, я удалил редактирование, чтобы избежать путаницы. Теперь вопрос вернулся к своему первоначальному варианту.
Вы можете зарегистрировать свой собственный конвертер для Qt::Alignment где-нибудь при запуске приложения (надеюсь, вы не захотите избежать этого взлома). Вот пример
QMetaType::registerConverter<Qt::Alignment, QString>([](const Qt::Alignment &align) {
static const QMap<Qt::Alignment, QString> alignMap {{Qt::AlignLeft, "AlignLeft"},
{Qt::AlignRight, "AlignRight"},
{Qt::AlignHCenter, "AlignHCenter"},
{Qt::AlignJustify, "AlignJustify"},
{Qt::AlignAbsolute, "AlignAbsolute"},
{Qt::AlignTop, "AlignTop"},
{Qt::AlignBottom, "AlignBottom"},
{Qt::AlignVCenter, "AlignVCenter"},
{Qt::AlignBaseline, "AlignBaseline"}};
QString textResult;
for (auto [alignKey, alignText] : alignMap.asKeyValueRange())
{
if (alignKey & align)
{
textResult.append(alignText);
textResult.append("|");
}
}
if (!textResult.isEmpty())
{
textResult.removeLast();
}
return textResult;
});
Очень хорошее решение. То, что я назвал хаком, было чем-то, что либо работало бы QVariant::toString, либо работало только для этого, и его нужно было бы повторить, чтобы сделать текст одинаковым в нескольких местах. Ваше решение делает настроенный текст доступным в QVariant::toString, QStyledItemDelegate::displayText (хороший рендеринг в моделях) и позволяет копировать/вставлять его из представлений (+, возможно, другие вещи, которые мне еще предстоит протестировать). Судя по всему, его не нужно регистрироваться при запуске, это можно сделать в любой момент.
Я не думаю, что это было бы возможно: как только перечисление обрабатывается с помощью ИЛИ, оно теоретически теряет любой исходный аспект своего определения, а преобразование QVariant фундаментально перебирает перечисление на основе его результирующего значения, без каких-либо знаний о том, как оно было. построен. Он использует QMetaEnum::valueToKeys(), поэтому вы можете проверить исходники, чтобы увидеть, как это реализовано.