Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: alexman от Апрель 20, 2011, 21:49



Название: Медленно работает drawPixmap.
Отправлено: alexman от Апрель 20, 2011, 21:49
1. Есть QGraphicsView. В качестве вьюпорта установлен QGLWidget.
2. Есть наследник от QGraphicsItem c переопределенным методом paint. В связи с багом в Qt реализовал свое кеширование айтема. Примерный код:
Код:
void paint( QPainter* painter, const QStyleOptionGraphicsItem*, QWidget* = 0 )
{
      const QRectF& rect = painter->worldTransform().inverted().mapRect( QRectF( painter->viewport() ) );
      if ( changed( rect ) ) { //Если текущая область изменилась, то перерисовываем кеш _cache - внутреннее поле класс, QPixmap _cache.
            _cache = QPixmap( painter->viewport().size() );
            _cache.fill( QColor( 0, 0, 0, 0 ) );

           //Рисовка в кеш.
      }

      //Отображение кеша:
      painter->setWorldMatrixEnabled( false );
      painter->drawPixmap( 0, 0, _cache );
      painter->setWorldMatrixEnabled( true );
}

Так вот под Windows XP для некоторых моделей NVIDIA-карт медленно работает painter->drawPixmap( 0, 0, _cache ); Проявил следующим образом: открыл notepad и поводил по окну - перерисовка тормозит. Как можно данный косяк оптимизировать? Заранее спасибо!


Название: Re: Медленно работает drawPixmap.
Отправлено: GreatSnake от Апрель 21, 2011, 08:34
Цитировать
В связи с багом в Qt реализовал свое кеширование айтема.
Интересно - что за баг?
Цитировать
Проявил следующим образом: открыл notepad и поводил по окну - перерисовка тормозит. Как можно данный косяк оптимизировать?
А разве на QGLWidget backing store не работает?

Попробуй вместо QPixmap использовать QImage.

Имхо у тебя что-то не так с дизайном, т.к. этот наследник QGraphicsItem завазан на painter->viewport().size().
Для чего вообще это делается? Если для отрисовки подложки, то лучше использовать QGraphicsView::drawBackground().


Название: Re: Медленно работает drawPixmap.
Отправлено: alexman от Апрель 21, 2011, 09:06
Цитировать
В связи с багом в Qt реализовал свое кеширование айтема.
Интересно - что за баг?
Кеш с ключом QGraphicsItem::DeviceCoordinateCache в последней версии не работает! Ранее работал.

Цитировать
Попробуй вместо QPixmap использовать QImage.
Попробую!

Цитировать
Имхо у тебя что-то не так с дизайном, т.к. этот наследник QGraphicsItem завазан на painter->viewport().size().
Для чего вообще это делается? Если для отрисовки подложки, то лучше использовать QGraphicsView::drawBackground().
Что не так то ??? Есть айтем, у него свой кеш, который меняется, когда текущий view rect изменился. Ну а далее при следующих вызывах рисуется только QPixmap.


Название: Re: Медленно работает drawPixmap.
Отправлено: GreatSnake от Апрель 21, 2011, 09:10
Как и при каких условиях у тебя задаётся painter->viewport()?


Название: Re: Медленно работает drawPixmap.
Отправлено: alexman от Апрель 21, 2011, 09:14
Как и при каких условиях у тебя задаётся painter->viewport()?
В смысле? Из Qt Assistant:
Код:
QRect QPainter::viewport () const
Returns the viewport rectangle.
Мной явно нигде это не задается! Максимум что я вызываю - это void QGraphicsView::fitInView ( const QRectF & rect, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio ).


Название: Re: Медленно работает drawPixmap.
Отправлено: GreatSnake от Апрель 21, 2011, 09:20
Т.е. получается, что размер твоего айтема всегда равен размеру твоего QGraphicsView?
Тогда зачем он вообще нужен? Ведь всё можно отрисовать в QGraphicsView::drawBackground().


Название: Re: Медленно работает drawPixmap.
Отправлено: alexman от Апрель 21, 2011, 09:27
Говорил же код примерный! Можно сделать пересечение с boundingRect() и тогда уже размер айтема не будет равен размеру QGraphicsView.

Код:
Тогда зачем он вообще нужен? Ведь всё можно отрисовать в QGraphicsView::drawBackground().
Айтемов может быть много и хотелось бы оставить qt-ый механизм рисовки! Может что-то не пойму! Что даст QGraphicsView::drawBackground()? Я же указал тонкое место. Медленно работает drawPixmap.


Название: Re: Медленно работает drawPixmap.
Отправлено: GreatSnake от Апрель 21, 2011, 09:36
Цитировать
Можно сделать пересечение с boundingRect() и тогда уже размер айтема не будет равен размеру QGraphicsView.
Кстати, а QGraphicsItem::boundingRect() не забыл правильно перегрузить?

Цитировать
Что даст QGraphicsView::drawBackground()?
Отрисовка будет делаться только для clipping region и достаточно быстро, т.к. в этом случае не придётся делать composing.
С отрисовкой QGraphicsItem может быть всё намного сложнее.



Название: Re: Медленно работает drawPixmap.
Отправлено: alexman от Апрель 21, 2011, 09:43
Цитировать
Можно сделать пересечение с boundingRect() и тогда уже размер айтема не будет равен размеру QGraphicsView.
Кстати, а QGraphicsItem::boundingRect() не забыл правильно перегрузить?
Неа.

Цитировать
Что даст QGraphicsView::drawBackground()?
Отрисовка будет делаться только для clipping region и достаточно быстро, т.к. в этом случае не придётся делать composing.
С отрисовкой QGraphicsItem может быть всё намного сложнее.
Да, но есть одно но: айтемы могут менять (довольно часто, приложение интерактивное) и всё равно придется все перерисовывать. В реализованом же случае перерисовывать необходимо будет только изменный айтем и это плюс в моем случае, так как рисовка затратная!