Qt的双缓冲技术(double buffering)

2022-09-03 11:20:52 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

Qt的双缓冲技术(double buffering)是Qt绘画机制的一部分,是一种在Qt4中被全面采用的技术。其核心是:把一个窗口部件渲染到一个脱屏pixmap(off- screen pixmap)中,然后再把这个pixmap复制到显示屏幕上。这样做的目的是用于消除屏幕的闪烁并且因而界面会显得更漂亮。Qt4中,Qt会自动处理这些情况,所以在普通的绘画中,我们不必要关注这些内容。

QT取消双缓冲的方法是setAttribute( Qt::WA_PaintOnScreen) 在更详细的说明这一技术前,gemfield需要简单介绍一下Qt的绘画机制。Qt的绘画机制本质上是提供了2个工具:QPainter和 QPaintDevice,分别代表人类世界的画笔和画板。Gemfield要完成一次绘画,就必须有个画笔(QPainter),另外,还得解决画笔画在哪儿(画板,QPaintDevice)的问题。Qt中的画板是QPaintDevice,当然,gemfield用到的都是它的子类,也就是具体哪种画板:它们是:QWidget、 QImage、QPicture、 QPixmap等,也就是每一个可见的控件(QWidget的子类)都是画板(在其paintEvent()里绘画)。 那么gemfield本文开始处提到的双缓冲技术是怎么做到消除屏幕闪烁的呢?其核心原因有2点: 1、 把核心的绘制工作转到屏幕之外完成,而在屏幕显示的时候,只是简单的内存复制。 2、 只对窗口部件的一部分进行重绘时,另外一部分就不需要重绘,也变成了简单的内存复制——将当前界面不需要重绘的像素复制到脱屏像素,再在脱屏像素上完成剩余的绘制,再通过内存复制映射到屏幕显示上。 Gemfield再通过一个叫做GemfieldFuwaArrow的程序(内含一个简单的绘制函数,其运行在SYSZUXpad上)简单介绍一下: void SYSZUXArrow::syszuxRotate(float angle) { this_angle=angle; refreshPixmap(); update(); } 1、 当SYSZUXpad通过总线接收到的角度有变化时,就调用refreshPixmap()函数来进行重新绘制,不过这是在脱屏的pixmap上进行绘制。然后再调用update()来执行paintEvent()。 void SYSZUXArrow::refreshPixmap() { pixmap->fill(this,0,0); this_width=width();//控件的宽度 this_height=height();//控件的高度 QColor this_color(127, 0, 127);//颜色 static const QPoint syszux_arrow[3] = { QPoint(this_width/2, 10), QPoint(this_width/2 5, 20), QPoint(this_width/2-5, 20) };//箭头的坐标 QPainter painter(pixmap); painter.initFrom(this); painter.setRenderHint(QPainter::Antialiasing, true); QPen pen(Qt::white); painter.setPen(pen); painter.drawLine(0,this_height/2,this_width,this_height/2);//x painter.drawLine(this_width/2,0,this_width/2,this_height);//y QPen syszux_pen(this_color,2); //QPainter painterArrow(pixmap); painter.setRenderHint(QPainter::Antialiasing, true); painter.setPen(syszux_pen); painter.translate(this_width/2,this_height/2); painter.setBrush(this_color); painter.rotate(this_angle); painter.translate(-this_width/2,-this_height/2); painter.drawLine(this_width/2,this_height/2,this_width/2,20); int a=(this_height/2.0-10)-((this_height/2-20)/100.0*gemfield_percent); painter.drawEllipse(this_width/2-10,a,20,20); painter.drawConvexPolygon(syszux_arrow, 3); } 2、在refreshPixmap()函数中,pixmap->fill(this,0,0);函数使用this控件的背景色或背景图片来填充当前脱屏的这个pixmap,后面两个参数是偏移量,也就是this左上角的点映射到pixmap上的哪里。这里是0,就表明完全重合、一模一样。 painter.initFrom(this);函数可以设置painter所使用的画笔、背景色、字体,让其和this控件一样。 void SYSZUXArrow::paintEvent(QPaintEvent *) { QPainter painter(this); painter.drawPixmap(0,0,*pixmap); } 3、 通过把pixmap复制到窗口部件的(0,0)位置来完成整个图形的绘制工作。 其实,在这样一个简单的绘图工作中,这样的技术大可不必。而且随着半导体技术的进步,双缓冲所能发挥出的功能相对减少。 另外一个不容忽视的问题是,使用双缓冲技术会增加系统的负载。因为相比普通的绘制,它多出了一些工作。比如在SYSZUXpad上运行 GemfieldFuwaArrow程序时,双缓冲时cpu的利用率是50%,而没有采用双缓冲时,cpu的利用率是37%。 其实这也说明了一个本质的问题,界面的绚烂总是靠硬件性能的提升获得的

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/143445.html原文链接:https://javaforall.cn

0 人点赞