Q_ENUMS с перечислением в заголовочном файле - PullRequest
0 голосов
/ 02 мая 2019

Я хочу использовать элементы перечисления в качестве элементов в QComboBox. Я могу сделать это, если enum определен в том же классе, но я бы хотел использовать enum, определенный в заголовочном файле. Моя цель - использовать перечисление непосредственно из файла заголовка, не изменяя файл заголовка. Более того, я хотел бы, чтобы мой код адаптировался к изменяющемуся перечислению, как по названию элементов, так и по их количеству.

Я нашел этот ответ и эту ссылку , которые помогли мне понять, как заполнить QComboBox перечислением. Решение в ответе работает для меня, но только если в классе определено перечисление.

Базовый код, который я хотел бы реализовать, выглядит следующим образом:

definitions.h

#ifndef _DEFINITIONS_H_
#define _DEFINITIONS_H_

typedef enum
{
     FIRST = 0,
     SECOND,
     THIRD
} elements;

#endif

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "definitions.h"

 class MainWindow : public QMainWindow
 {
   Q_OBJECT
   Q_ENUMS(elements);

 public:
   explicit MainWindow(QWidget *parent = 0);
   QComboBox *comboBox;

 };

 #endif 

mainwindow.cc

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
 QMainWindow(parent),
{
  int index = metaObject()->indexOfEnumerator("elements");
  QMetaEnum metaEnum = metaObject()->enumerator(index);

  for (int i = 0; i < metaEnum.keyCount(); i++)
      comboBox->addItem(metaEnum.valueToKey(i));
 }

Этот код не сталкивается с какими-либо проблемами при компиляции во время выполнения, но не оказывает никакого влияния. Определение перечисления в классе MainWindow работает как шарм.

Это не похоже на проблему видимости, потому что я могу использовать элементы enum в своем коде, и я не столкнулся с какой-либо проблемой компиляции.

Я попытался переопределить мой enum в mainwindow.h с помощью typedef, но безуспешно:

typedef elements new_elements

Я также пытался заменить Q_ENUMS на Q_ENUM, как предлагается в ответе ниже, но результат тот же.

Можно ли использовать Q_ENUMS / Q_ENUM с перечислением, определенным в заголовочном файле? Что я должен делать по-другому?

Ответы [ 2 ]

1 голос
/ 02 мая 2019

Вы не можете этого сделать. Q_ENUMS нужен мета-объект, предоставляемый либо классом QObject, либо макросом Q_GADGET, поэтому он работает, когда перечисление объявлено в классе, производном от QObject.

Начиная с Qt 5.8, появился новый макрос Q_ENUM_NS, который делает это возможным:

Этот макрос регистрирует тип enum в мета-объектной системе. Он должен быть помещен после объявления enum в пространство имен, в котором есть макрос Q_NAMESPACE. Он такой же, как Q_ENUM, но в пространстве имен.

Вы можете сделать что-то подобное:

namespace MyNamespace {

    Q_NAMESPACE

    enum elements {
     FIRST = 0,
     SECOND,
     THIRD
    };

    Q_ENUM_NS(elements)
}

См. сообщение для получения дополнительной информации.

Обновление

Что касается последнего комментария, вы можете создать новое перечисление и связать каждый элемент со значением нового.

 class MainWindow : public QMainWindow {
   Q_OBJECT
 public:   
     enum elements {
         FIRST = ::elements::FIRST,
         SECOND = ::elements::SECOND,
         THIRD = ::elements::THIRD,
     };
     Q_ENUM(elements);
}

Тогда для такой функции, как:

void use_enum(elements e);

// Call it with the original one
use_enum(elements::FIRST);
// Call it with the new one, you just created
use_enum(MainWindow::elements::FIRST);
0 голосов
/ 02 мая 2019

Проверьте Q_ENUM, который автоматически регистрируется как метатип, как сказано в документации Что нового в Qt 5.5 :

Добавлен Q_ENUM для замены Q_ENUMS, что позволяет получитьQMetaEnum во время компиляции с использованием QMetaEnum :: fromType.Такие перечисления теперь автоматически регистрируются как метатипы и могут быть преобразованы в строки в QVariant или напечатаны как строка с помощью qDebug ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...