PDA

View Full Version : Delegate paint optimisation



bunjee
21st April 2008, 15:55
Here is two delegated QListView of 1000 items,
One is fast, the other is slow.

http://bunjeee.free.fr/slowFast.png

When the area is wider, the painting is *much* slower.

Here is my delegate paint function

void ZeChatRoom_delegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
// QItemDelegate::paint(painter, option, index);

ZeChatRoom_data * chatData = index.data().value<ZeChatRoom_data *>();

// Display rects
QRect pictureRect(option.rect.x() + 2, option.rect.y() + 2, 32, 32);

QRect displayRect = QRect(option.rect.x() + 36, option.rect.y() + 2,
option.rect.width() - 38, (option.rect.height() - 4) / 2);

QRect displayRect2 = QRect(option.rect.x() + 36, option.rect.y() + option.rect.height() / 2,
option.rect.width() - 38, (option.rect.height() - 4) / 2);

QColor textColor = Qt::black;
QColor descriptionColor = ZeStyle::get()->getDarkBorderColor();

if (option.state & QStyle::State_MouseOver)
{
ZePainterController::get()->DrawHighlight(*painter, option.rect);

textColor = ZeStyle::get()->getHighlightTextColor();
descriptionColor = ZeStyle::get()->getHighlightTextColor();

ZePainterController::get()->
DrawBottomLine(*painter, option.rect, QColor(100, 100, 100, 150));
}
else
{
if (index.row() %2 == 0)
{
ZePainterController::get()->
DrawBack(*painter, option.rect, QColor(ZeStyle::get()->getBorderColor().red(),
ZeStyle::get()->getBorderColor().green(),
ZeStyle::get()->getBorderColor().blue(), 50), false);
}

ZePainterController::get()->
DrawBottomLine(*painter, option.rect,
/*QColor(100, 100, 100, 150)*/ QColor(ZeStyle::get()->getBorderColor().red(),
ZeStyle::get()->getBorderColor().green(),
ZeStyle::get()->getBorderColor().blue(), 200));
}

ZePainterController::get()->
DrawPictureRatio(*painter, *chatData->mChatPixmap, pictureRect, 1.0f);

QFont font;
font.setBold(true);
ZePainterController::get()->DrawText(*painter,
displayRect,
chatData->mRoomName + " - " + QString::number(chatData->mParticipants),
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine,
textColor,
&font);

ZePainterController::get()->DrawText(*painter,
displayRect2,
chatData->mDescription,
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine,
descriptionColor);
}

Is there a way to optimize the painting ? Especially when you're painting plain grey rectangles at each refresh.

wysota
21st April 2008, 16:17
Hard to say without knowing what all those functions of yours do.

bunjee
21st April 2008, 16:33
This one draws the grey background:


void ZePainterController::DrawBack(QPainter & painter, const QRect &rect,
const QColor & color, const bool border)
{
QRect rectBase;

if (border)
{
QPen pen;
pen.setBrush(ZeStyle::get()->getBorderColor());
painter.setPen(pen);

rectBase.setRect(rect.x(), rect.y(),
rect.width() - 1, rect.height() - 1);
}
else
{
painter.setPen(Qt::NoPen);

rectBase.setRect(rect.x(), rect.y(),
rect.width(), rect.height());
}

painter.setBrush(QColor(color.red(), color.green(), color.blue(), color.alpha()));
painter.drawRect(rectBase);
}

This one draws the text:


void ZePainterController::DrawText(QPainter & painter,
const QRectF & rect,
const QString & text,
int flags,
const QColor & color,
const QFont * font,
const bool elided)
{
painter.save();

QString finalText;

if (font)
{
painter.setFont(*font);
}

if (elided)
{
QFontMetrics fontMetric(painter.font());
finalText = fontMetric.elidedText(text,
Qt::ElideRight,
rect.width());
}
else
{
finalText = text;
}

QPen pen;

pen.setBrush(color);
painter.setPen(pen);

painter.drawText(rect, flags, finalText);

painter.restore();
}

This one draws the picture


void ZePainterController::DrawPictureRatio(QPainter & painter, QPixmap & pixmap,
const QRect &rect, const float opacity)
{
int gapWidth = 0;
int gapHeight = 0;

if (rect.width() > pixmap.width())
{
gapWidth = (rect.width() - pixmap.width()) / 2;
}
if (rect.height() > pixmap.height())
{
gapHeight = (rect.height() - pixmap.height()) / 2;
}

QRect displayRect(rect.x() + gapWidth, rect.y() + gapHeight,
pixmap.width(), pixmap.height());

DrawPicture(painter, pixmap, displayRect, opacity);
}

...Hope that didn't kill you :).

wysota
21st April 2008, 16:42
I don't see any reason why increasing the width should significantly reduce rendering speed. Have you tried using a profiler to find the bottleneck?

bunjee
21st April 2008, 16:48
Maybe it's my QT 4.4 Release candidate. I'll do some more tests :/

wysota
21st April 2008, 16:59
No, there is really nothing that would cause such a slowdown there, regardless of the Qt version used. I really suggest profiling.

bunjee
21st April 2008, 17:25
Alright,
Transparency seems to be the problem.

I have several QListViews in a list of widget.

The listviews have their back set to transparent :

QPalette palette;
palette.setColor(QPalette::Base, QColor(0, 0, 0, 0));
mListView->setPalette(palette);

The widget list has a custom paint event, painting a custom color.

Several layers of transparency seems to reduce performances.

wysota
21st April 2008, 17:31
Where exactly do you have those layers of transparency?

bunjee
21st April 2008, 18:02
I had the following paint event in my *Home made* list of widgets:


void ZeBaseListWidget::paintEvent(QPaintEvent * event)
{
mScrollArea->setBackgroundColor(mListColor);
QPainter painter(this);

painter.setPen(Qt::NoPen);
if (mListColor == Qt::white)
{
painter.setBrush(ZeStyle::get()->getColorList());
}
else
{
painter.setBrush(mListColor);
}

painter.drawRect(rect());
}

Now I'm doing like that:


QPalette palette;
palette.setColor(QPalette::Background, color);
setPalette(palette);

If specify the background palette instead of painting it, performances are better.

On the flipside, I have to notify my widget list everytime the background color changes.

wysota
21st April 2008, 18:41
What is mScrollArea? By the way, there are some flags you might use to optimize performance. Caching some things might also speed up things. If you still didn't run your code through a profiler, I really suggest to do that.

bunjee
21st April 2008, 19:56
mScrollArea was commented.

Yes, I'll do some profiling. I need to work on memory consumption too, since my program is quite heavy.

Do you have a particular tool to suggest ?

Beside this, model view approach works great.


Off topic, but I like your retargetting implementation (QRetargetScale) on your blog.

Thanks for all the help you provided me,
I'll put your name and blog in the "about" of my program :).

wysota
21st April 2008, 20:48
Do you have a particular tool to suggest ?
Depends what OS you are using. I'd suggest gprof or valgrind (cachegrind, to be exact) if they are available for your platform.


Off topic, but I like your retargetting implementation (QRetargetScale) on your blog.

Thanks for all the help you provided me,
I'll put your name and blog in the "about" of my program :).

Thx :)