[Qt教程] 第18篇 2D绘图(八)双缓冲绘图

简介:
楼主
  发表于 2013-5-2 22:07:23  | 查看: 789 | 回复: 1
双缓冲绘图


版权声明

该文章原创于Qter开源社区(www.qter.org),作者yafeilinux,转载请注明出处!


导语

在前面一节中,讲述了如何实现简单的涂鸦板,这一次我们将实现在涂鸦板上绘制图形,这里以矩形为例进行讲解。在后面还会提出双缓冲绘图的概念。


环境: Windows Xp + Qt 4.8.4+QtCreator 2.6.2


目录

一、绘制矩形
二、双缓冲绘图


正文


一、绘制矩形

1. 我们仍然在前面程序的基础上进行修改,先更改painEvent() 函数:
void   Dialog ::paintEvent( QPaintEvent   *)
{
     QPainter   painter( this );
     int   x,y,w,h;
     x   =   lastPoint .x();
     y   =   lastPoint .y();
     w   =   endPoint .x()   -   x;
     h   =   endPoint .y()   -   y;
     painter.drawRect(x,   y,   w,   h);
}
        这里就是通过lastPoint endPoint 两个点来确定要绘制的矩形的起点、宽和高的。运行程序,用鼠标拖出一个矩形,效果如下图所示。
18-1.jpg



2.  上面已经可以拖出一个矩形了,但是这样直接在窗口上绘图,以前画的矩形是不能保存下来的。所以我们下面加入画布,在画布上进行绘图。将paintEvent() 函数更改如下:
void   Dialog ::paintEvent( QPaintEvent   *)
{
     int   x,y,w,h;
     x   =   lastPoint .x();
     y   =   lastPoint .y();
     w   =   endPoint .x()   -   x;
     h   =   endPoint .y()   -   y;
     QPainter   pp(& pix );
     pp.drawRect(x,   y,   w,   h);
     QPainter   painter( this );
     painter.drawPixmap( 0 ,   0 ,   pix );
}
        这里就是将图形先绘制在了画布上,然后将画布绘制到窗口上。我们运行程序,然后使用鼠标拖出一个矩形,发现出现了很多重影,效果如下图所示。
18-2.jpg


        为什么会出现这种现象呢?大家可以尝试分别快速拖动鼠标和慢速拖动鼠标来绘制矩形,结果会发现,拖动速度越快,重影越少。其实,在我们拖动鼠标的过程中,屏幕已经刷新了很多次,也可以理解为paintEvent() 函数执行了多次,每执行一次就会绘制一个矩形。知道了原因,就有方法来避免这个问题发生了。


二、双缓冲绘图

1. 我们再添加一个辅助画布,如果正在绘图,也就是鼠标按键还没有释放的时候,就在这个辅助画布上绘图,只有当鼠标按键释放的时候,才在真正的画布上绘图。
        首先在dialog.h 文件中添加两个私有变量:

QPixmap   tempPix ;   // 辅助画布
bool   isDrawing ;     // 标志是否正在绘图

        然后到dialog.cpp 的构造函数中对变量进行初始化:

isDrawing   =   false ;

下面再更改paintEvent() 函数:
void   Dialog ::paintEvent( QPaintEvent   *)
{
     int   x,y,w,h;
     x   =   lastPoint .x();
     y   =   lastPoint .y();
     w   =   endPoint .x()   -   x;
     h   =   endPoint .y()   -   y;
     QPainter   painter( this );
     if ( isDrawing )   // 如果正在绘图,就在辅助画布上绘制
     {
        // 将以前pix中的内容复制到tempPix中,保证以前的内容不消失
        tempPix   =   pix ;
        QPainter   pp(& tempPix );
        pp.drawRect(x,y,w,h);
        painter.drawPixmap( 0 ,   0 ,   tempPix );
     }   else   {
        QPainter   pp(& pix );
        pp.drawRect(x,y,w,h);
        painter.drawPixmap( 0 , 0 , pix );
     }
}

        下面还需要更改鼠标按下事件处理函数和鼠标释放事件处理函数的内容:

void   Dialog ::mousePressEvent( QMouseEvent   *event)
{
     if (event->button()== Qt :: LeftButton )   // 鼠标左键按下
     {
        lastPoint   =   event->pos();
        isDrawing   =   true ;     // 正在绘图
     }
}
void   Dialog ::mouseReleaseEvent( QMouseEvent   *event)
{
     if (event->button()   ==   Qt :: LeftButton )   // 鼠标左键释放
     {
        endPoint   =   event->pos();
        isDrawing   =   false ;      // 结束绘图
        update();
     }
}
        当鼠标左键按下时我们开始标记正在绘图,当按键释放时我们取消正在绘图的标记。现在运行程序,已经可以实现正常的绘图了。效果如下图所示。
18-3.jpg


2. 双缓冲绘图
        根据这个例子所使用的技巧,我们引出所谓的双缓冲绘图的概念。双缓冲(double-buffers )绘图,就是在进行绘制时,先将所有内容都绘制到一个绘图设备(如QPixmap )上,然后再将整个图像绘制到部件上显示出来。使用双缓冲绘图可以避免显示时的闪烁现象。从Qt 4.0 开始,QWidget 部件的所有绘制都自动使用了双缓冲,所以一般没有必要在paintEvent() 函数中使用双缓冲代码来避免闪烁。
        虽然在一般的绘图中无需手动使用双缓冲绘图,不过要想实现一些绘图效果,还是要借助于双缓冲的概念。比如这个程序里,我们要实现使用鼠标在界面上绘制一个任意大小的矩形。这里需要两张画布,它们都是QPixmap 实例,其中一个tempPix 用来作为临时缓冲区,当鼠标正在拖动矩形进行绘制时,将内容先绘制到tempPix 上,然后将tempPix 绘制到界面上;而另一个pix 作为缓冲区,用来保存已经完成的绘制。当松开鼠标完成矩形的绘制后,则将tempPix 的内容复制到pix 上。为了绘制时不显示拖影,而且保证以前绘制的内容不消失,那么在移动鼠标过程中,每绘制一次,都要在绘制这个矩形的原来的图像上进行绘制,所以需要在每次绘制tempPix 之前,先将pix 的内容复制到tempPix 上。因为这里有两个QPixmap 对象,也可以说有两个缓冲区,所以称之为双缓冲绘图。



结语

         对于Qt基本绘图的内容,我们就讲到这里,如果大家还想更加系统深入的学习这些基础知识,可以参考《Qt Creator快速入门》的第10章。从下一节开始,我们将简单介绍一下Qt中得图形视图框架。




涉及到的源码:    painter_3.zip (2.74 KB, 下载次数: 9)
相关文章
|
4月前
(14)Qt绘图(one)
本文介绍了在Qt中使用QPainter进行绘图的基础操作,包括如何指定绘图设备、使用QPen和QBrush设置线条和填充样式、绘制不同样式的线条和形状,以及如何实现纹理填充和渐变填充等效果。
95 6
(14)Qt绘图(one)
|
4月前
|
计算机视觉
(15)Qt绘图(two)
Qt框架中QPainter类的多种绘图功能,包括坐标变换、基本图形绘制、文本和图片绘制、图像保存以及碰撞检测等。
68 1
(15)Qt绘图(two)
|
6月前
Qt绘图之QWidget
Qt绘图之QWidget
116 1
|
7月前
|
数据安全/隐私保护 C++ 计算机视觉
Qt(C++)开发一款图片防盗用水印制作小工具
文本水印是一种常用的防盗用手段,可以将文本信息嵌入到图片、视频等文件中,用于识别和证明文件的版权归属。在数字化和网络化的时代,大量的原创作品容易被不法分子盗用或侵犯版权,因此加入文本水印成为了保护原创作品和维护知识产权的必要手段。 通常情况下,文本水印可以包含版权声明、制作者姓名、日期、网址等信息,以帮助识别文件的来源和版权归属。同时,为了增强防盗用效果,文本水印通常会采用字体、颜色、角度等多种组合方式,使得水印难以被删除或篡改,有效地降低了盗用意愿和风险。 开发人员可以使用图像处理技术和编程语言实现文本水印的功能,例如使用Qt的QPainter类进行文本绘制操作,将文本信息嵌入到图片中,
245 1
|
6月前
|
监控 C++ 容器
【qt】MDI多文档界面开发
【qt】MDI多文档界面开发
208 0