Archived:Painting only the dirty area of the widget in Qt
| Line 11: | Line 11: | ||
==Overview== | ==Overview== | ||
| − | This example shows how to paint only | + | This example shows how to paint only an area of the widget whose content has been marked as invalid and needs to be updated. That will speed up UI painting. |
When user draws line using stylus on the sceen is line first painted into QPixmap picture and | When user draws line using stylus on the sceen is line first painted into QPixmap picture and | ||
| Line 98: | Line 98: | ||
p2 = QPoint(-1, -1); | p2 = QPoint(-1, -1); | ||
| − | // Opaquea paint, we paint only | + | // Opaquea paint, we paint only changed area of the screen |
setAttribute(Qt::WA_OpaquePaintEvent, true); | setAttribute(Qt::WA_OpaquePaintEvent, true); | ||
} | } | ||
| Line 175: | Line 175: | ||
QPainter painter(this); | QPainter painter(this); | ||
| − | // Paint only | + | // Paint only changed area of the screen |
if (testAttribute(Qt::WA_OpaquePaintEvent)) { | if (testAttribute(Qt::WA_OpaquePaintEvent)) { | ||
painter.setClipRegion(dirtyRect()); | painter.setClipRegion(dirtyRect()); | ||
Revision as of 10:01, 6 November 2009
Article Metadata
Tested with
Devices(s): Nokia 5800 eXpressMusic, Nokia N900
Compatibility
Platform(s): Qt
Article
Keywords: WA_OpaquePaintEvent, QPainter::setClipRegion()
Created: (20 Oct 2009)
Last edited: tepaa
(06 Nov 2009)
Contents |
Overview
This example shows how to paint only an area of the widget whose content has been marked as invalid and needs to be updated. That will speed up UI painting.
When user draws line using stylus on the sceen is line first painted into QPixmap picture and then picture is updated into screen. Application updates only dirty area of picture on line drawing.
Dirty area painting can be handled setting Qt::WA_OpaquePaintEvent attribute of widget as true and defining dirty rect to QPainter with QPainter::setClipRegion().
Preconditions
- Qt is installed on your platform
- Download Qt for Symbian release from here: [1]
- Qt on Maemo can be found here: Qt4 Maemo port
Header
#include <QtGui>
class Widget: public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
void mouseMoveEvent(QMouseEvent *);
void mousePressEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
void paintEvent(QPaintEvent *);
void resizeEvent(QResizeEvent *);
private:
void paintToPixmap();
void paintLine(QPainter&);
QRect dirtyRect();
private:
QPoint p1;
QPoint p2;
QPen pen;
QColor color;
QPixmap pixmap;
};
Source
Widget::Widget(QWidget *parent) :
QWidget(parent)
{
p1 = QPoint(-1, -1);
p2 = QPoint(-1, -1);
color = QColor(Qt::black);
pen.setColor(color);
pen.setStyle(Qt::SolidLine);
pen.setWidth(2);
}
Widget::~Widget()
{
}
void Widget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
// Create pixmap that size is same as screen has
pixmap = QPixmap(event->size());
pixmap.fill(Qt::white);
}
void Widget::mousePressEvent(QMouseEvent *event)
{
p1 = event->pos();
p2 = QPoint(-1, -1);
// Opaquea paint, we paint only changed area of the screen
setAttribute(Qt::WA_OpaquePaintEvent, true);
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
if (p2.x() == -1) {
p2 = event->pos();
}
else {
p1 = p2;
p2 = event->pos();
}
// Paint to pixmap and then pixmap on screen
paintToPixmap();
}
void Widget::mouseReleaseEvent(QMouseEvent *)
{
// Stop using opaquea paint
setAttribute(Qt::WA_OpaquePaintEvent, false);
// Update screen
update();
}
void Widget::paintToPixmap()
{
// Paint line to pixmap
QPainter painter;
painter.begin(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(pen);
paintLine(painter);
painter.end();
// Draw pixmap on the screen
update();
}
void Widget::paintLine(QPainter& painter)
{
if (p1.x() != -1 && p2.x() != -1) {
painter.drawLine(p1, p2);
}
}
QRect Widget::dirtyRect()
{
int left, top, width, height;
if (p1.x() == -1 || p2.x() == -1) {
return rect();
}
if (p1.x() < p2.x()) {
left = p1.x();
width = p2.x() - p1.x();
}
else {
left = p2.x();
width = p1.x() - p2.x();
}
if (p1.y() < p2.y()) {
top = p1.y();
height = p2.y() - p1.y();
}
else {
top = p2.y();
height = p1.y() - p2.y();
}
return QRect(left - 15, top - 15, width + 30, height + 30);
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
// Paint only changed area of the screen
if (testAttribute(Qt::WA_OpaquePaintEvent)) {
painter.setClipRegion(dirtyRect());
}
// Update pixmap into screen. If dirty
// area is set painter updates only that
painter.drawPixmap(QPoint(0, 0), pixmap);
}
Postconditions
Screen updates fast.

