Пишу приложение, в котором необходимо, что бы картинка фона графической сцены постепенно менялась, скажем, с таймером. В документации прочитал, что необходимо пронаследовать 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%цп, ужас!!!). Собственно, мой вопрос: КАК наиболее правильно и оптимально обновить этот задний фон в моем случае?
Вопрос решен. С моей стороны было очень глупо вызывать update() прямо из drawBackground(). По хорошему, функция drawBackground() должна перерисовывать ЛИШЬ фон, и больше ничего. Я создал таймер в моем классе QCustomScene, который раз в 25 мс вызывает функцию QGraphicsScene::update(). Перенес все операции на сцене в слот этого таймера. В итоге я получаю таймер, который позволяет мне легко контролировать ФПС моей программы, а так же нагрузку на процессор <1%.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Привет, делаю сайт визитку, затык на банальном вопросе не могу вставить изображение на фон только одной (главной) indexhtml страницы
Интересует какими лучше способами нарисовать (анимировать само рисование спирали) спираль Ферма на сайте? (Чтобы пользователь видел как...