Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Система рисования. Печать _ Моргание при отрисовке QImage

Автор: wiz29 2.12.2010, 15:08

Столкнулся со следующей проблемой: имеется некая сцена которая отрисовывается в QImage imgScene. (отрисовка происходит в отдельном потоке) имеется метод для копирования изображения (копия сцены рисутеся в гуи потоке) Возникает следующий эффект http://s013.radikal.ru/i325/1012/d6/792b6748b025.png такое ощущение что картинка еще не успела появится на экране приходит следующий paint event. Вопрос, как можно синхронизировать и почему получается такой эффект (картинка не успевает дорисоваться до конца сверху вниз).

Автор: BRE 2.12.2010, 15:13

А как происходит синхронизация этих двух изображений? В какой момент копируется из потока в GUI?

Автор: wiz29 2.12.2010, 15:17

Когда картинка содержащая изображение сцены готова, то посылается сигнал объекту гуи потока, по этому сигналу объект gui потока вызывает метод в котором происходит копирование QImageй, дальше рабочий поток вновь заполняет свои данные (оповещение объекта gui потока происходит не чаще чем через 40мс)

Автор: BRE 2.12.2010, 15:19

А в потоке ожидается момент, когда GUI-поток скопирует картинку или сразу начинается формирование следующего кадра?

Автор: wiz29 2.12.2010, 15:22

да , там синхронизация по мьютексу


но копирование происходит посредством оператора = мб в это м проблема?

естьли смысл копировать из QImage например в QPixmap? (не будет ли при этом тормознее)

Автор: BRE 2.12.2010, 15:23

Т.е. ты посылаешь сигнал и блокируешь поток. А разблокируешь его только после завершения копирования?

Автор: wiz29 2.12.2010, 15:48

ну когда срабатывает слот у объекта gui потока он вызывает метод у объекта рабочего потока по копированию, на момент копирования вызывается локер, таким образом если QImage в объекте рабочего потока находится в занятом состоянии то gui объект будет ждать завершения данной операции и захватит после этого мьютекс, ну и наоборот аналогично.

Просто ведь в QImage используется implicit share data copy может в этом проблема?

но тогда сомнительная выгода от использования рисования в QImage в отдельном потоке.

у меня сложилось ощущение что нужно делать вертикальную синхронизацию. Только как пока незнаю

Автор: BRE 2.12.2010, 16:08

Вот смотри. Рабочий поток закончил формирование кадра, послал сигнал, этот сигнал положился в очередь GUI-потока, рабочий поток начал изменять картинку, в этот момент происходит переключение на GUI поток, который вызывает слот для копирования картинки, но она уже частично изменилась.
Или само рисование в рабочем потоке тоже закрывается мутексом?

Одно из решений использовать в рабочем потоке двойной буферизации.
Нарисовали кадр на первой картинке, отправили сигнал, переключились на вторую картинку и начали формировать следующий кадр. GUI-поток, получив сигнал о изменении, копирует себе первую готовую картинку. Рабочий поток завершил формировать следующий кадр на второй картинки, отсылает сигнал и переключается на первую, а GUI-поток копирует себе вторую картинку и все повторяется.
В этом варианте тоже есть тонкий момент: если формирующий поток будет успевать формировать несколько кадров, а GUI-поток, соответственно, не будет успевать их получать.

Автор: wiz29 2.12.2010, 16:32

Щас попробую, просто ощущение создалось такое что нужно как то vsync сделать, не успевает вывести на экран.

не не помогло, полазил на форумах нокии там рекомендуют как использовать 1н паинтер для виджета , пишут что вроде как должно помоч.

Автор: BRE 2.12.2010, 16:35

Цитата(wiz29 @ 2.12.2010, 16:32) *
не не помогло, полазил на форумах нокии там рекомендуют как использовать 1н паинтер для виджета , пишут что вроде как должно помоч.

Как понять "1н паинтер для виждета"? :)


Автор: wiz29 2.12.2010, 16:38

ну не создавать каждый раз в paintEvent новый паинтер а иметь однажды инициализированый, хотя мне пока не помогло:)

щас попробую воспроизвести в тестовом приложении мою ситуацию

Автор: BRE 2.12.2010, 16:48

Цитата(wiz29 @ 2.12.2010, 16:38) *
ну не создавать каждый раз в paintEvent новый паинтер а иметь однажды инициализированый, хотя мне пока не помогло:)

Это где такие глупости написаны? Это совершенно не так. QPainter это класс-рисовальщик, его объекты просто предоставляют методы для рисования на уже созданном QPaintDevice, не более. Поэтому его нужно (и можно) создавать каждый раз, особенно в paintEvent. :)

Автор: wiz29 2.12.2010, 17:28

мне это тоже показалось весьма странным, но я попробовал и не помогло:))

сделал тестовый пример, рисует нормально, значит ошибка гдето в коде , спасибо за помощь.

Автор: wiz29 3.12.2010, 10:53

Разобрался с проблемой. Просто у нас есть некое двигло по сведению нескольких картинок, а локов на уровне двигла как оказалось не было отсюда и результат: 1 поток пишет в контейнер данные, 2 асинхронно читает из движка. Эффект блинка возникал когда частично прочитанная картинка начинала обновлятся в другом потоке:)

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)