Как наиболее корректно обновлять фон QGraphicsScene?

283
18 ноября 2017, 11:53

Пишу приложение, в котором необходимо, что бы картинка фона графической сцены постепенно менялась, скажем, с таймером. В документации прочитал, что необходимо пронаследовать QGraphicsScene и переопределить метод drawBackground. Функция принимает указатель на QPainter и прямоугольник QRect, который надо перерисовать. Итак, в случае, когда картинка фона не меняется, а двигается только один обьект - в моем случае главный герой моей "игры" - красный треугольничек - все проходит нормально. Выглядит это примерно так:

    QPixmap cropped;
    QRect rscn(hor_offset, ver_offset, WIDTH, HEIGHT);
    cropped = bg_image.copy(rscn);
    painter->setPen(Qt::NoPen);
    painter->drawPixmap(0, 0, WIDTH, HEIGHT, cropped);

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

Все было бы хорошо, да как бы не так. В случае, если герой дошел до края сцены, то оффеты начинают меняться - и фон вместе со всеми декорациями начинает двигаться. Код, который выполняется в функции QGraphicsScene::drawBackground() в данном случае:

if (offsets_changed) {
    QPixmap cropped;
    QRect rscn(hor_offset, ver_offset, WIDTH, HEIGHT);
    cropped = bg_image.copy(rscn);
    painter->setPen(Qt::NoPen);
    painter->drawPixmap(0, 0, WIDTH, HEIGHT, cropped);
    QPolygon poly(rscn);
    //Removing all old items from scene
    foreach (auto dec_item, temp_decs) {
        this->removeItem(dec_item);
        delete dec_item;
    }
    temp_decs.clear();
    foreach (Decoration *dec, dec_vec) {                         /*Here we are looking for all decorations
                                                                  which we should see on this part of global map*/
        QPolygon is = poly.intersected(dec->Polygon());
        if (!is.isEmpty()) {                                     /*If we found any decoration intersected with our
                                                                  vision rect, we cut the peace of this decoration
                                                                  and create new decoration as this peace, then
                                                                  we add it as an object to our scene*/
            is.translate(-1 * hor_offset, -1 * ver_offset);
            Decoration *ndec = new Decoration(is);               /*Creating new decoration and saving it in vector
                                                                  to delete later*/
            temp_decs.push_back(ndec);
            this->addItem(ndec);
        }
    }
    //this->update(rect.toRect());
}

Работает перерисовка всех обьектов, НО нормально не перерисовывается сцена. Как видите, когда сцена "подвинулась" перерисовка произошла корректно в том числе и для boundingRect'a треугольника - но фон нормально не перерисовался. Единственное рабочее решение, которое я нашел, вызывать QGraphicsScene::update() прямо из функции drawBackground() после всех изменений (в прошлом коде эта строчка закоментирована). Если так сделать - фон правильно двигается и обновляется. Но ужасно подскакивает производительность (15% цп -> 30%цп, ужас!!!). Собственно, мой вопрос: КАК наиболее правильно и оптимально обновить этот задний фон в моем случае?

Answer 1

Вопрос решен. С моей стороны было очень глупо вызывать update() прямо из drawBackground(). По хорошему, функция drawBackground() должна перерисовывать ЛИШЬ фон, и больше ничего. Я создал таймер в моем классе QCustomScene, который раз в 25 мс вызывает функцию QGraphicsScene::update(). Перенес все операции на сцене в слот этого таймера. В итоге я получаю таймер, который позволяет мне легко контролировать ФПС моей программы, а так же нагрузку на процессор <1%.

READ ALSO
Сайт визитка html/css

Сайт визитка html/css

Привет, делаю сайт визитку, затык на банальном вопросе не могу вставить изображение на фон только одной (главной) indexhtml страницы

323
Отрисовать спираль на сайте

Отрисовать спираль на сайте

Интересует какими лучше способами нарисовать (анимировать само рисование спирали) спираль Ферма на сайте? (Чтобы пользователь видел как...

379
Не работает iframe

Не работает iframe

Сайт на wordpress, добавил в запись через админку такой код:

328