双缓冲主要用于图形用户界面的开发,包括把一个窗口部件渲染到一个像素图,和把这个像素图绘制到屏幕上。
和自定义窗口部件一样,需要从 QWidget 继承一个类,然后至少要重写 paintEvent() 函数,还需要一个 QPixmap 作为窗口部件渲染的像素图。
class Widget : public QWidget
{
Q_OBJECT
public :
Widget( QWidget * parent = 0 );
~ Widget();
protected :
void paintEvent( QPaintEvent * event);
private :
QColor changeColor();
private Q_SLOTS :
void refresh();
private :
QPixmap * pixmap;
QTimer * timer;
int r;
int g;
int b;
};
Widget 类重写了 QWidget 的 paintEvent() 函数,使用了 QTimer 定时刷新屏幕,声明了 refresh 槽来接受 QTimer 的信号。
Widget:: Widget( QWidget * parent)
: QWidget ( parent), r( 0 ), g( 0 ), b( 0 )
{
pixmap = new QPixmap ( size());
pixmap-> fill( this , 0 , 0 );
timer = new QTimer ( this );
connect( timer, SIGNAL ( timeout()), this , SLOT ( refresh()));
timer-> start( 10 );
}
Widget::~ Widget()
{
if ( pixmap != 0 )
delete pixmap;
if ( timer-> isActive())
timer-> stop();
delete timer;
}
在构造函数里创建了渲染的目标像素图和计时器,并将计时器的 timeout 信号和窗口的 refresh 槽相连接,然后启动计时器,时间间隔为 10ms 。在析构函数里销毁像素图和计时器。
void Widget:: refresh()
{
if ( pixmap != 0 ){
delete pixmap;
}
pixmap = new QPixmap ( size());
pixmap-> fill( this , 0 , 0 );
QPainter painter( pixmap);
painter. fillRect( rect(), changeColor());
update();
}
在 refresh() 里面,先清空像素图里面的内容,将大小调整为窗口部件的大小,然后用默认的颜色来填充像素图。然后用 QPainter 在像素图上绘制。最后用 update() 来为整个窗口部件预约一个重绘事件,这个事件将激活 paintEvent() 。
void Widget:: paintEvent( QPaintEvent * /*event*/ )
{
QPainter painter( this );
painter. drawPixmap( 0 , 0 , * pixmap);
}
绘制事件很简单,直接将像素图绘制在屏幕上即可。
QColor Widget:: changeColor()
{
r = r< 255 ? ++ r : r;
g = g< 255 ? ++ g : g;
b = b< 255 ? ++ b : b;
return QColor ( r, g, b);
}
这个例子是用不同的颜色填充窗口部件,所以还有一个控制颜色变化的函数。这个和整个双缓冲机制无关。