Ukio_G
@Ukio_G
Незамысловатый юноша.

Как организовать хранение элементов, чтобы к некоторым можно было обратиться по имени?

Здравствуйте.
Есть ряд объектов - 3D объекты (класс Object3D), Линии (Line_3D), Скайбоксы (Skybox) и так далее.
Допустим, они являются унаследованы от класса Drawable, который выглядит так:
class Drawable{
public:
    virtual void draw(QOpenGLFunctions * functions, Camera * camera, QMatrix4x4 projection_matrix) = 0;
};


Это дает возможность создать очередь отрисовки, и в цикле openGL использовать следующую конструкцию:
// Где-то вне цикла отрисовки
   QList<Drawable *> drawQueue;

   // ...

void WidgetGL::paintGL() {

    foreach (Drawable drawable, objList)
        drawable.draw(context()->functions(),&_camera,m_projectionMatrix);

}


Хорошо.
Теперь рассмотрим ситуацию.
У нас есть 3 линии, которые образуют базис, который располагается в точке O(0;0;0)
Line_3D * ox = new Line_3D(QVector3D(0.0,0.0,0.0),QVector3D(1.0,0.0,0.0),QVector3D(1.0,0.0,0.0));
    Line_3D * oy = new Line_3D(QVector3D(0.0,0.0,0.0),QVector3D(0.0,1.0,0.0),QVector3D(0.0,1.0,0.0));
    Line_3D * oz = new Line_3D(QVector3D(0.0,0.0,0.0),QVector3D(0.0,0.0,1.0),QVector3D(0.0,0.0,1.0));

    drawQueue.append(dynamic_cast<Drawable*>(ox));
    drawQueue.append(dynamic_cast<Drawable*>(oy));
    drawQueue.append(dynamic_cast<Drawable*>(oz));


Перед тем, как эти 3 линии были добавлены в лист drawQueue, к этому листу было добавлено произвольное количество как объектов Line_3D и Object3D

Теперь синтетический пример:
В какой-то момент потребовалось обратиться к одной из линий базиса, но это совершенно невозможно, если мы не знаем индекса, под которым эта линия была добавлена в drawQueue.

Какие решения проблемы могут быть?

Сейчас я создал для хранения всех объектов дополнительный класс SceneComponents:
class SceneComponents : public QObject
{
    Q_OBJECT
public:
    explicit SceneComponents(QObject *parent = nullptr);

    void addDrawable(Drawable * drawable);
    QList<Drawable *> getDrawQueue() const;

private:
    QList<Drawable *> drawQueue;

    QList<Object3D *> _object3dList;
    QList<Line_3D *> _line3dList;
    QList<Skybox *> _skyboxList;
    QList<Ray *> _rayList;

};


Несколько основных идей, которые у меня есть на этот счет:
1) У класса Drawable создать поле name, или наследовать Line_3D, Skybox, Object3D и Ray от QObject - и использовать objectName и setObjectName.
Очень спорный способ, потому что для поиска объекта придется перебирать все объекты в одном из листов ( _object3dList, _line3dList, ... )
2) Использовать QMap, в который по необходимости будет добавляться указатель на объект класса Drawable, в качестве ключа использовать QString:
class SceneComponents : public QObject
{
    Q_OBJECT
public:
    explicit SceneComponents(QObject *parent = nullptr);

    void addDrawable(Drawable * drawable);
    QList<Drawable *> getDrawQueue() const;

private:
    QList<Drawable *> drawQueue;

    QList<Object3D *> _object3dList;
    QList<Line_3D *> _line3dList;
    QList<Skybox *> _skyboxList;
    QList<Ray *> _rayList;

   QMap<QString,Drawable*> _objectByName;
};

Данный способ мне нравится больше, однако тогда если какой-либо объект будет удален (вызван delete), надо будет обновлять остальные списки объекта класса SceneComponents (ведь никто не хочет вызвать метод draw у объекта, который удален)

Почему вместо QList не использовать только QMap?
Потому что не всем объектам нужны будут имена. Это значит, что не для всех объектов предполагается наличие имени, что тоже нужно учитывать.
  • Вопрос задан
  • 74 просмотра
Решения вопроса 1
IGHOR
@IGHOR Куратор тега Qt
Qt/C++ DEV/CTO
А вы QMap<QString,Drawable*> _objectByName; замените на QMap<Drawable*, QString> _objectByName;
Тогда имя может быть пустым, а достать объект по имени можно через метод key(..)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы