Политика конфиденциальностиКонтактыО сайтеОтзывыGitHubDonate
© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB
n
3 сентября 2018 г. 15:55

Меню уровней на QML и C++

c++, QML

Здравствуйте, хочу сделать динамически формируемое меню уровней для игры (то есть меню которое в зависимости от числа уровней имеющихся например в файле XML выводит нужное количество на экран). И не много не понимаю как такое реализовать в купе с QML.

Создал специальный класс для блока уровня (пока выводит лишь треугольники) *.h:

#ifndef MODULEPARTMENUELEMENT_H
#define MODULEPARTMENUELEMENT_H

#include <QQuickItem>
#include <QSGGeometryNode>
#include <QSGFlatColorMaterial>

class ModulePartMenuElement : public QQuickItem
{
    Q_OBJECT
    Q_PROPERTY(bool isActive READ isActive WRITE setIsActive NOTIFY isActiveChanged)
    Q_PROPERTY(QColor activeColor READ activeColor WRITE setActiveColor NOTIFY activeColorChanged)
    Q_PROPERTY(QColor nonActiveColor READ nonActiveColor WRITE setNonActiveColor NOTIFY nonActiveColorChanged)
public:
    ModulePartMenuElement(QQuickItem *parent = 0);


    bool isActive() const;
    QColor activeColor() const;
    QColor nonActiveColor() const;

protected:
    virtual QSGNode * updatePaintNode(QSGNode *node, UpdatePaintNodeData *updatePaintNodeData) override;

signals:
    void isActiveChanged(bool isActive);
    void activeColorChanged(QColor activeColor);
    void nonActiveColorChanged(QColor nonActiveColor);

public slots:
    void setIsActive(const bool isActive);
    void setActiveColor(const QColor activeColor);
    void setNonActiveColor(const QColor nonActiveColor);

private:
    //состояние элемента
    bool _isActive;
    //фон если активен
    QColor _activeColor;
    //фон если не активен
    QColor _nonActiveColor;
    
};

#endif // MODULEPARTMENUELEMENT_H

*.cpp:
#include "modulepartmenuelement.h"

ModulePartMenuElement::ModulePartMenuElement(QQuickItem *parent) : QQuickItem(parent)
{
    

    setFlag(QQuickItem::ItemHasContents, true);
}

bool ModulePartMenuElement::isActive() const
{
    return _isActive;
}

QColor ModulePartMenuElement::activeColor() const
{
    return _activeColor;
}

QColor ModulePartMenuElement::nonActiveColor() const
{
    return _nonActiveColor;
}

QSGNode *ModulePartMenuElement::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *updatePaintNodeData)
{
    Q_UNUSED(updatePaintNodeData)
    QSGGeometryNode *node = static_cast<QSGGeometryNode*>(oldNode);
    
    if (!node)
    {
        node = new QSGGeometryNode();
        node->setFlag(QSGNode::OwnsMaterial, true);
        node->setFlag(QSGNode::OwnsGeometry, true);
    }
        const QRectF rect = boundingRect();
        //геометрия
        QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 3);

        QSGGeometry::Point2D *points = geometry->vertexDataAsPoint2D();
        points[0].x = rect.left();
        points[0].y = rect.top();
        points[1].x = rect.left() + rect.width() / 2.0;
        points[1].y = rect.bottom();
        points[2].x = rect.right();
        points[2].y = rect.top();

        node->setGeometry(geometry);
        QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
        if (_isActive)
        {
            material->setColor(_activeColor);

        }
        else
        {
            material->setColor(_nonActiveColor);
        }
        node->setMaterial(material);

        return node;

    
}

void ModulePartMenuElement::setIsActive(const bool isActive)
{
    if (_isActive == isActive)
        return;
    _isActive = isActive;
    emit isActiveChanged(isActive);
}

void ModulePartMenuElement::setActiveColor(const QColor activeColor)
{
    if (_activeColor == activeColor)
        return;
    _activeColor = activeColor;
    emit activeColorChanged(activeColor);
}

void ModulePartMenuElement::setNonActiveColor(const QColor nonActiveColor)
{
    if (_nonActiveColor == nonActiveColor)
        return;
    _nonActiveColor = nonActiveColor;
    emit nonActiveColorChanged(nonActiveColor);
}

Как я думаю, начинать надо с создания класса модели, наследуемой от абстрактной модели, в которую передается список блоков уровней (Из которого можно убрать всю взаимосвязь с QML, так как он делался под статическое размещение элементов) и модель устанавливается в стандартный вьювер в QML, но, насколько я понимаю, нужно будет еще и создавать класс делегата для отображения блока уровня в QML. (И тут возникает путаница, ведь отображение рисуется уже в созданном мной классе блока уровня или я чего-то не понимаю?) Или может быть все это можно сделать несколько проще?
Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
4
a
  • 3 сентября 2018 г. 19:32

Может я неправильно понял задачу, но я бы делал все в QML. У ListModel есть методы append и clear. Данные из файла можно считывать в с++ классе и передавать в QML элемент.

В updatePaintNode, для Android, нормально можно рисовать только треугольниками (полигоны и квадраты вроде неподдерживаются), что усложнит весь процесс.


0
n

Для меня просто qml темный лес), вот и пытаюсь разобраться. Прочитав ваш ответ в голове сформировал алгоритм: 1) при запуске main.qml вызываю метод в с++ классе по обработке файла

2) после обработки сигналами класса с++ передаю в методы append циклично информацию о добавлении блока уровня (мой треугольеик)
3) в qml подключен мой класс треугольник и происходит добавление его в модель, вот только я не совсем понимаю, как при добавлении в модель менять свойства треугольника(цвет, активность)? Для этого нужно в с++ классе по обработке файла, в сигнал вешать параметры? Или можно как-то подругому?
И еще не понятно с делегатом? Его тоже нужно сделать от класса? Или как мой треугольник будет отображаться.
Просто никак не могу понять это взаимодействие qml и с++ в сложных примерах. И особо информации не найти. Везде только примеры в духе 2+2. Если бы не предпологалось сделать на андроид, давно бы похоронил этот qml и сделал бы все на плюсах





0
a
  • 4 сентября 2018 г. 8:53
  • (ред.)

Здесь на сайте есть урок QML - 007. Урок про динамическое создание элементов. 1) 2) Можно добавлять элементы при первом открытии меню уровней, можно при создании. 3) Настроить вид элемента можно в делегате. Можно не использовать класс треугольника. В делегат можно добавить MouseArea, в обработчик onClicked, можно добавить изменение к-н свойства элемента делегата. Все есть в уроках на сайте.


0
n
  • 30 сентября 2018 г. 14:01
  • (ред.)

В итоге сумел реализовать то что хотел в своем первоначальном вопросе. Но насколько моя реализация получилась грамотной не знаю. Поэтому, кому интересно, прошу посмотреть проект и указать на недочеты или плохую реализацию, если таковые имеются.

0

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
МБ
21 апреля 2019 г. 9:40
Моисей Бушуев

Qt - Тест 001. Сигналы и слоты

  • Результат:0баллов,
  • Очки рейтинга-10
AA
17 апреля 2019 г. 19:40
Anton Ablin

Qt - Тест 001. Сигналы и слоты

  • Результат:73баллов,
  • Очки рейтинга1
E
17 апреля 2019 г. 18:16
Evgeny

Qt - Тест 001. Сигналы и слоты

  • Результат:100баллов,
  • Очки рейтинга10
Последние комментарии
21 апреля 2019 г. 16:22
Евгений Легоцкой

Через метод setIcon table.horizontalHeaderItem(0).setIcon("qrc://path/to/icon.png")
21 апреля 2019 г. 15:48
Евгений Легоцкой

Добрый день! Спасибо за комментарий. Там действительно лучше будет сделать с инициализацией по умолчанию.
U
18 апреля 2019 г. 15:37
Unreal_man

А как иконку в хедер задать?
u
18 апреля 2019 г. 2:15
uaa

доброго времени,большое спасибо за пример для начинающего)при адаптации к своему проекту столкнулся с таким ньансом:в vepolyline.h в 47 строке нужна инициализация по умолчанию: int m_pointF...
E
11 апреля 2019 г. 12:49
Evgeny

Спасибо за ответ) У меня компоновщик на нее ругался просто. Оказалось, просто забыл Q_OBJECT в начале класса указать.
Сейчас обсуждают на форуме
23 апреля 2019 г. 18:39
BlinCT

Вопрос закрыт) проблема найдена
21 апреля 2019 г. 16:16
Евгений Легоцкой

Приветствую Нужно сохранять где-то выбранное значение, а потом восстанавливать его. Или использовать QSettings или добавить метод open(), в который передавать начальные значения для того...
R
19 апреля 2019 г. 9:55
RED_Spider

мені важко це зараз навіть перевірити, тому що знайшов коміт, це ще було в 2016 році, і цей код не буде працювати коректно зараз, єдине скажу що це були QThread
i
17 апреля 2019 г. 15:03
ilya.guzikov

BlinCT, на стороне ++ это делать необходимо так как в qml при использовании функции append происходит перерисовка всех точек лини(как я понимаю) и из-за этого при использовании больших массиво...
Присоединяйтесь к нам в социальных сетях

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы