Название: [РЕШЕНО] Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: marbius от Апрель 25, 2010, 10:27 Доброго времени суток.
Совершенно случайно наткнулся на такую неприятную (при большом количестве выводимых объектов) "особенность": при изменении размеров окна, на котором происходит отрисовка через QPaintEvent, Возможно ли как-то изменить ситуацию так, чтобы, например, при изменении размера окна по вертикали по rect() возвращалась только недостающая нижняя часть окна, действительно необходимая для "дорисовки"? Спасибо. Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: alexman от Апрель 25, 2010, 10:34 Используй void QWidget::resizeEvent( QResizeEvent * event ). А в QResizeEvent можно использовать для анализа методы const QSize & oldSize () const, const QSize & size () const.
Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: alexman от Апрель 25, 2010, 10:39 А const QRect & QPaintEvent::rect () const всегда возвращает всю область?
Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: marbius от Апрель 25, 2010, 11:05 Используй void QWidget::resizeEvent( QResizeEvent * event ). А в QResizeEvent можно использовать для анализа методы const QSize & oldSize () const, const QSize & size () const. Как тогда можно убрать из очереди отрисовку всей области, попадающую в QPaintEvent после изменения размеров окна? Получается, что область перерисовывается трижды: дважды я инициирую дорисовку "справа" и "снизу", а затем идет обычное сообщение опять-таки на обновление всей области. (введение флагов не помогло) А const QRect & QPaintEvent::rect () const всегда возвращает всю область? Не совсем понял вопроса. Я писал, что при изменении размеров окна Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: alexman от Апрель 25, 2010, 11:50 Используй void QWidget::resizeEvent( QResizeEvent * event ). А в QResizeEvent можно использовать для анализа методы const QSize & oldSize () const, const QSize & size () const. Как тогда можно убрать из очереди отрисовку всей области, попадающую в QPaintEvent после изменения размеров окна? Получается, что область перерисовывается трижды: дважды я инициирую дорисовку "сверху" и "снизу", а затем идет обычное сообщение опять-таки на обновление всей области. (введение флагов не помогло) А const QRect & QPaintEvent::rect () const всегда возвращает всю область? Не совсем понял вопроса. Я писал, что при изменении размеров окна paintRect возвращает всю область, от (0;0) по (width;height). Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: marbius от Апрель 25, 2010, 12:04 Цитировать void QWidget::paintEvent ( QPaintEvent * event ) тоже переопредели! Цитировать Написано же про rect! Метод paintRect даже не нашел! Извини, но непродуктивный "разговор": кто-то кого-то не понимает, скорее всего, я. если я "рисую" самостоятельно, то, скорее всего, метод у меня и так переопределен. вопрос в том, что перерисовка при изменении размеров попадает в очередь, и соответственно в обработчик события, помимо моей воли, так сказать из недр qt. Вопрос сейчас в том, как это можно предотвратить. Я подозреваю, что это происходит из-за перерисовки фона, но могу и ошибаться. А paintRect - это не метод, это просто моя опечатка. Увы, но разговор шел именно про const QRect & QPaintEvent::rect () const и именно этот метод возвращает нули... Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: alexman от Апрель 25, 2010, 12:10 Еще можно использовать флаг Qt::WA_OpaquePaintEvent.
Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: marbius от Апрель 25, 2010, 12:24 Еще можно использовать флаг Qt::WA_OpaquePaintEvent. Увы, все те же (0;0) только теперь уже без фона :( Скорее всего придется смириться с медленной отрисовкой.... Но, все же как-то же это должно решаться... alexman, спасибо за потраченное время. Вопрос открыт. Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: alexman от Апрель 25, 2010, 13:33 1. Хранить текущий rect и предыдущий rect (оба в глобальных координатах).
2. В void QWidget::resizeEvent ( QResizeEvent * event ), void QWidget::moveEvent ( QMoveEvent * event ) rect-ы пересчитываются. 3. В void QWidget::paintEvent ( QPaintEvent * event ) рисовка (по обоим rect-ам можно проанализировать, что перерисовывать). 4. QPoint QWidget::mapToGlobal ( const QPoint & pos ) const - получинение глобальных координат. Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: marbius от Апрель 25, 2010, 13:51 1. Хранить текущий rect и предыдущий rect (оба в глобальных координатах). 2. В void QWidget::resizeEvent ( QResizeEvent * event ), void QWidget::moveEvent ( QMoveEvent * event ) rect-ы пересчитываются. 3. В void QWidget::paintEvent ( QPaintEvent * event ) рисовка (по обоим rect-ам можно проанализировать, что перерисовывать). 4. QPoint QWidget::mapToGlobal ( const QPoint & pos ) const - получинение глобальных координат. Спасибо за ответ, но соль в том, что: а) если "не извращаться", то потом при выходе из QWidget::resizeEvent, в очереди все мои попытки отрисовать свои прямоугольники "съедаются" глобальной перерисовкой с координатами (0;0; width*height); б) если "поизвращаться" и ввести разного рода флаги-блокировки, то получается, что контент будет отрисовываться трижды, как я уже писАл, причем самое печальное, что опять-таки последней будет глобальная перерисовка. Возможный вариант решения, как всегда прост и уже неоднократно описан: использовать QPixmap, и при QWidget::paintEvent выводить только его, а уже при QWidget::resizeEvent расчитывать свои прямоугольники и выводить на QPixmap. Все же думал, что есть более "прямое" решение. Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: alexman от Апрель 25, 2010, 13:56 Возможный вариант решения, как всегда прост и уже неоднократно описан: использовать QPixmap, и при QWidget::paintEvent выводить только его, а уже при QWidget::resizeEvent расчитывать свои прямоугольники и выводить на QPixmap. Все же думал, что есть более "прямое" решение. Да, это быстро работает! Проверенно много раз!Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: marbius от Апрель 25, 2010, 14:07 Да, это быстро работает! Проверенно много раз! Offtopic Но это лишние затраты памяти. И к тому же насколько я понял, в Qt и так используется буферизация вывода, а так получается, что еще один дополнительный буфер. Вот это меня смущает при использовании QPixmap. Поправьте меня, если я ошибаюсь. Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: Igors от Апрель 25, 2010, 14:44 1) Какую область (region, rectangle) нужно перерисовывать - занимается ОС. Не видно оснований почему при resize нужно "инвалидировать" только часть - в большинстве случаев окно должно быть полностью обновлено если его размер изменился
2) Кто буферирует - дело темное (платформо-зависимое). Напр. на Mac это сам OC 3) QPixmap - верная дорога. Опасения по поводу расходов на буфер беспочвенны. Прикинем: окно 1024 х 1024, расход памяти 4 Мб. Это по нынешним временам не объем. Для сравнения если Вы масштабируете картинку в несколько раз - очень быстро расходы превышают 100 Мб, но я еще не видел попыток сэкономить память на этом :) Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: marbius от Апрель 25, 2010, 15:03 ... Не видно оснований почему при resize нужно "инвалидировать" только часть - в большинстве случаев окно должно быть полностью обновлено если его размер изменился... Ну, я могу возразить (опять-таки частный случай): я тяну окошко за нижнюю границу, у меня невалидная только та часть, которая появляется снизу. Или вот более худший вариант: есть QWidget - главное окно, в котором находится еще один QWidget - мой виджет, допустим размером 100х100 пикселей, причем для главного окна я установил setMinimumSize (200, 200); я меняю размеры главного окна (тяну мышью, например). Зачем мне перерисовывать дочерний виджет каждый раз при изменении размеров главного окна? (возможно, этот вариант больше offtopic и суть другой темы, но все же имеет место быть). Чтож, QPixmap - все же более верное и быстрое решение, чем копаться в недрах qt. Принимаю последнее как решение проблемы. Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: GreatSnake от Апрель 26, 2010, 09:54 Qt::WA_StaticContents
Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: marbius от Апрель 26, 2010, 10:59 Qt::WA_StaticContents Цитировать Indicates that the widget contents are north-west aligned and static. On resize, such a widget will receive paint events only for parts of itself that are newly visible. This flag is set or cleared by the widget's author. К сожалению, теория расходится с практикой: перерисовывается область (0;0; width*height) Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: GreatSnake от Апрель 26, 2010, 11:44 Цитировать К сожалению, теория расходится с практикой: перерисовывается область (0;0; width*height) Похоже, что именно так и есть.Есть большое подозрение, что тролли оставили поддержку этого флага только для top-level окон. Кстати, вы не указали paintEvent() какого виджета отрабатывает? Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: marbius от Апрель 26, 2010, 12:15 Как всегда, все гениальное просто :)
Установка следующих аттрибутов решает проболему: setAttribute(Qt::WA_StaticContents,true); setAttribute(Qt::WA_NoBackground,true); Всем спасибо. Вопрос закрыт. Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: marbius от Апрель 26, 2010, 12:17 Кстати, вы не указали paintEvent() какого виджета отрабатывает? наследника от QWidget Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: alexman от Апрель 26, 2010, 12:20 Qt::WA_NoBackground - This value is obsolete. Use WA_OpaquePaintEvent instead.
Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: marbius от Апрель 26, 2010, 12:23 Qt::WA_NoBackground - This value is obsolete. Use WA_OpaquePaintEvent instead. Согласен. Только ОБЯЗАТЕЛЬНО совместно с Qt::WA_StaticContents, т.е. чтобы оба указанных аттрибута были установлены: РЕШЕНИЕ Код: setAttribute(Qt::WA_StaticContents,true); Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: alexman от Апрель 26, 2010, 12:39 Qt::WA_NoBackground - This value is obsolete. Use WA_OpaquePaintEvent instead. Согласен. Только ОБЯЗАТЕЛЬНО совместно с Qt::WA_StaticContents, т.е. чтобы оба указанных аттрибута были установлены: Код: setAttribute(Qt::WA_StaticContents,true); Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: marbius от Апрель 26, 2010, 12:45 Мои извинения, что не указал изначально, но это решение для Windows-платформы, на других еще не проверял. Возможно, там появятся свои нюансы (грабли).
Название: Re: Отрисовка части изображения в QPaintEvent при изменении размера окна Отправлено: GreatSnake от Апрель 26, 2010, 12:49 Под X11 работает.
|