Перечисления/флаги Qt и QVariant::toString

Любое значение типа Qt::Alignment (флаг) можно преобразовать в удобную для чтения строку, как показано ниже:

QString s = QVariant::fromValue<Qt::Alignment>(Qt::AlignTop | Qt::AlignLeft).toString();

Этот код заполняет sAlignLeading|AlignTop.
В некотором смысле это правильно, поскольку Qt::AlignLeading является синонимом Qt::AlignLeft. Я бы предпочел получить исходное значение, а не его синоним, хотя, по-видимому, команда Qt согласна, поскольку редактор свойств дизайнера Qt не упоминает синонимы.

Есть ли способ получить нужную мне строку с помощью функций только Qt, т.е. без какого-либо взлома?

Я не думаю, что это было бы возможно: как только перечисление обрабатывается с помощью ИЛИ, оно теоретически теряет любой исходный аспект своего определения, а преобразование QVariant фундаментально перебирает перечисление на основе его результирующего значения, без каких-либо знаний о том, как оно было. построен. Он использует QMetaEnum::valueToKeys(), поэтому вы можете проверить исходники, чтобы увидеть, как это реализовано.

musicamante 14.08.2024 17:14

Это не похоже на правду. Можно объявить флаги, для которых QVariant::toString возвращает пустую строку и в то же время QMetaEnum::valueToKeys() возвращает правильные данные.

Atmo 14.08.2024 18:02

Извините за путаницу. Я имел в виду valueToKey() (см. код qvariant.cpp, он никогда не использует функцию «ключи»). Именно по этой причине он возвращает нулевую строку: он возвращает только один известный ключ для определенного перечисления, если оно существует, поэтому перечисления с ИЛИ не будут учитываться, если они не определены (например: Qt.AlignCenter). Тем не менее, если проблема заключается в отображении значения в представлении элемента, самым простым решением было бы просто переопределить displayText() в делегате.

musicamante 14.08.2024 21:00

@musicamante Возможно, вы захотите взглянуть на принятый ответ.

Atmo 16.08.2024 14:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
84
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Чтобы понять проблему, следует посмотреть файл 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.

Atmo 16.08.2024 10:10

Кстати, я удалил редактирование, чтобы избежать путаницы. Теперь вопрос вернулся к своему первоначальному варианту.

Atmo 16.08.2024 12:55
Ответ принят как подходящий

Вы можете зарегистрировать свой собственный конвертер для 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 (хороший рендеринг в моделях) и позволяет копировать/вставлять его из представлений (+, возможно, другие вещи, которые мне еще предстоит протестировать). Судя по всему, его не нужно регистрироваться при запуске, это можно сделать в любой момент.

Atmo 16.08.2024 13:54

Другие вопросы по теме