[Qt-interest] Optimizing QPaintEvent and clipping
Bjoern Erik Nilsen
bnilsen at trolltech.com
Mon Feb 9 11:22:43 CET 2009
Hi Josh,
Josh wrote:
> Hello,
>
> I'm trying to reimplement QPaintEvent for a class subclassed from QWidget.
> I'm using a QPainter to paint a number of shapes (QRects in my example, ie
> QList<QRect> rects) onto the QWidget. Having gotten that to work, I'm
> trying to improve speed by only redrawing the parts of the widget that
> need repainting. I can see that QPaintEvent gives a QRect of the part of
> the widget that needs repainting. I thought the following would work:
>
> 1) Set the painter clip rectangle to be only the part that needs updating.
> The docs seemed to indicated that QPainter did this automatically
> anyway, but I wasn't sure. ?? Anyone know ??
You don't have to set any clip on the painter. This is already done in
the paint engine right before paintEvent() is called. Setting it on the
painter as well will just slow down the drawing. I'd also like to point
out that QPaintEvent::rect() is the same as
QPaintEvent::region().boundingRect(), so using QPaintEvent::rect() as
the clip is wrong in any case.
> 2) Clear the rectangle that needs updating.
This step is not needed in your case.
> 3) (Re)draw any rectangles that intersect with the rectangle that needs
> updating.
> I tried the following code to implement that, but it doesn't work. In
> particular, when the rects get covered and then uncovered, they aren't
> fully redrawn. Are there any simple examples that do this? Any pointers on
> what I'm doing wrong? Thanks so much.
Note that "rects[i]" (non-const operator[]) will cause the container to
detach (do a deep copy), so you should rather use "rects.at(i)" instead.
The pen is also static so you should store it in the class and re-use it.
Then you should end up with something like this:
void Widget::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing);
painter.setPen(pen);
const QRegion clip(e->region());
for (int i = 0; i < rects.size(); ++i) {
const QRect rect(rects.at(i));
if (clip.intersects(rect))
painter.drawRect(rect);
}
}
Hope this helps,
--
Bjørn Erik Nilsen
Software Engineer
Nokia, Qt Software
More information about the Qt-interest-old
mailing list