Реклама
  • EVILEG
  • Ответ
  • 20 декабря 2017 г. 21:30

QGraphicsScene

В общем смысл программы будет следующий. Вы открываете через диалоговое окно с файлами панорамы. Тайлы при этом должны иметь все одинаковые размеры (это искусственное ограничение, чтобы показать основной алгоритм, необходимые проверки потом сами реализуете, если будут тайлы разных размеров).

 
Записываете нужную информацию во вьюшку, то есть пути ко всем тайлам.
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    m_scene = new QGraphicsScene(this);
    ui->graphicsView->setScene(m_scene);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_clicked()
{
    // Открыть все необходимые тайлы
    ui->graphicsView->setTilePaths(QFileDialog::getOpenFileNames(this, tr("Open Tiles")));
}

В самой графической вьюшке будут вектора на тайлы, а также и на пути к тайлам, которые можно будет подгружать.
#ifndef TILEDGRAPHICSVIEW_H
#define TILEDGRAPHICSVIEW_H

#include <QGraphicsView>
#include <QGraphicsPixmapItem>

class TiledGraphicsView : public QGraphicsView
{
    Q_OBJECT
public:
    explicit TiledGraphicsView(QWidget *parent = nullptr);

    void setTilePaths(QStringList tilePaths);

protected:
    virtual void paintEvent(QPaintEvent* e) override;

private:
    QStringList m_tilePaths;    // Пути к тайлам
    int m_tileHeight;           // Высота тайла
    int m_tileWidth;            // Ширина тайла
    int m_tileSetWidth;         // Ширина графической сцены под тайлы
    int m_tileSetHeight;        // Высота графической сцены под тайлы

    std::vector<QGraphicsPixmapItem*> m_tileItems;  // Указатели на загруженные тайлы
};

#endif // TILEDGRAPHICSVIEW_H

Далее сам процесс отрисовки с установкой тайлов во вьюшку
#include "TiledGraphicsView.h"

#include <QPainter>
#include <QFile>
#include <QGLWidget>
#include <QScrollBar>

#include <QDebug>

TiledGraphicsView::TiledGraphicsView(QWidget *parent) : QGraphicsView(parent)
{
    setViewport(new QGLWidget(this));
}

void TiledGraphicsView::setTilePaths(QStringList tilePaths)
{
    // При загрузке нового сета тайлов очистим всё.
    scene()->clear();
    m_tilePaths.clear();
    m_tileItems.clear();

    m_tilePaths = tilePaths;

    // С помощью первого тайла найдём параметры графической сцены и тайла
    QImage firstTile(m_tilePaths.first());
    m_tileHeight = firstTile.height();
    m_tileWidth = firstTile.width();
    m_tileSetWidth = m_tileWidth * m_tilePaths.length();
    m_tileSetHeight = m_tileHeight;
    setSceneRect(0, 0, m_tileSetWidth, m_tileSetHeight);
}

void TiledGraphicsView::paintEvent(QPaintEvent *e)
{
    QRect drawRect(horizontalScrollBar()->value(),
                    verticalScrollBar()->value(),
                    viewport()->width(),
                    viewport()->height());

    // При каждом событии перерисовки проверяем, какие из тайлов нужно отрисовать
    for (int i = 0; i < m_tilePaths.length(); ++i)
    {
        int coordX1 = i * m_tileWidth;
        int coordX2 = coordX1 + m_tileWidth;
        // Если тайл попадает в область отрисовки
        if ((coordX1 >= drawRect.x() && coordX1 <= drawRect.x() + drawRect.width()) || (coordX2 >= drawRect.x() && coordX2 <= drawRect.x() + drawRect.width()))
        {
            // то пытаемся его отрисовать при условии, что он ещё не был отрисован
            auto it = std::find_if(m_tileItems.begin(), m_tileItems.end(), [&coordX1](const QGraphicsPixmapItem* pixmap) { return coordX1 == pixmap->pos().x(); } );
            if (it == m_tileItems.end())
            {
                QGraphicsPixmapItem* pixmapItem = scene()->addPixmap(QPixmap(m_tilePaths.at(i)));
                m_tileItems.push_back(pixmapItem);
                pixmapItem->setPos(coordX1, 0);
            }
        }
        else
        {
            // В противном случае удаляем его со сцены и из пула отрисованных тайлов с очисткой памяти
            auto it = std::find_if(m_tileItems.begin(), m_tileItems.end(), [&coordX1](const QGraphicsPixmapItem* pixmap) { return coordX1 == pixmap->pos().x(); } );
            if (it != m_tileItems.end())
            {
                scene()->removeItem(*it);
                delete *it;
                m_tileItems.erase(it);
            }
        }
    }

    QGraphicsView::paintEvent(e);
}
Реклама

C++ - Тест 003. Условия и циклы

  • Результат 35 баллов
  • Очки рейтинга -10
  • falcon
  • 16 января 2018 г. 17:25

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

  • Результат 100 баллов
  • Очки рейтинга 10
  • falcon
  • 16 января 2018 г. 17:22

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

  • Результат 68 баллов
  • Очки рейтинга -1
Последние комментарии

QML - Урок 021. Переключение между окнами в QML

Спасибо всем. Все получилось. Прикручиваю логику.

  • BlinCT
  • 14 января 2018 г. 19:28

Разработка на Qt под iOS

Вот честно, на сколько же муторно под огрызок что то делать. Куча проблем) А вод линь или под Андроид все просто и тривиально))

  • folax
  • 12 января 2018 г. 9:16

QML - Урок 021. Переключение между окнами в QML

Ничего сложного, делаете по тех заданию 3 файла qml, называете их как указанно в тех задании, потом из первого окна через Loader их переключаете, в окне 2 и 3 делаете сигналы которые при закры...

QML - Урок 021. Переключение между окнами в QML

Все верно, я и не говорил что этот кусок кода лично мое произведение. Это тоже верно: Это задание для прохождения на собеседование в одну из крупных украинских IT компаний. Логику ...

  • folax
  • 12 января 2018 г. 8:13

QML - Урок 021. Переключение между окнами в QML

int main(int argc, char *argv[]){ QApplication app(argc, argv); Logic logic; QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("logic", &logic)...

Сейчас обсуждают на форуме
  • EVILEG
  • 18 января 2018 г. 20:46

Как проверить доступность сервера

Тут скорее всего ситуативно, но по факту да, в большинстве задач можно обойтись и одним network менеджером

  • EVILEG
  • 18 января 2018 г. 20:46

QGraphicsScene

Как вариант умножать ключевые координаты, от которых вы строите весь панораму, на общую ширину панорамы и при прокрутке отталкиваться от этих кратных координат.

  • Ruslan
  • 18 января 2018 г. 11:51

Исключения. Потоки.

Все оказалось проще. Документацию то читал, но забыл нюансы. Не указывал в connect  тип подключения Qt::DirectConnection

ChartView. Отображение метки данных точки серии при наведении курсора

Спасибо большущее за советы! Все получилось через ScatterSeries. Методы remove() как-то сходу не дались, удаляет в первый раз, а потом программа падает... Не стал тратить время и воспользовалс...

  • EVILEG
  • 15 января 2018 г. 17:21

Qt webgl

Насчёт проверки подключения клиента я не в курсе. Что касается экземпляров приложения, то из того, что я читал получается, что нет необходимости в нескольких экземплярах для нескольких кл...