[Qt教程] 第18篇 2D绘图(八)双缓冲绘图
生活随笔
收集整理的這篇文章主要介紹了
[Qt教程] 第18篇 2D绘图(八)双缓冲绘图
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
[Qt教程]?第18篇 2D繪圖(八)雙緩沖繪圖
??|?查看: 789|?回復(fù): 1| 雙緩沖繪圖 版權(quán)聲明 該文章原創(chuàng)于Qter開源社區(qū)(www.qter.org),作者yafeilinux,轉(zhuǎn)載請注明出處! 導(dǎo)語 在前面一節(jié)中,講述了如何實(shí)現(xiàn)簡單的涂鴉板,這一次我們將實(shí)現(xiàn)在涂鴉板上繪制圖形,這里以矩形為例進(jìn)行講解。在后面還會提出雙緩沖繪圖的概念。 環(huán)境:Windows Xp + Qt 4.8.4+QtCreator 2.6.2 目錄 一、繪制矩形 二、雙緩沖繪圖 正文 一、繪制矩形 1.我們?nèi)匀辉谇懊娉绦虻幕A(chǔ)上進(jìn)行修改,先更改painEvent()函數(shù): 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兩個(gè)點(diǎn)來確定要繪制的矩形的起點(diǎn)、寬和高的。運(yùn)行程序,用鼠標(biāo)拖出一個(gè)矩形,效果如下圖所示。 2.?上面已經(jīng)可以拖出一個(gè)矩形了,但是這樣直接在窗口上繪圖,以前畫的矩形是不能保存下來的。所以我們下面加入畫布,在畫布上進(jìn)行繪圖。將paintEvent()函數(shù)更改如下: 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); } 這里就是將圖形先繪制在了畫布上,然后將畫布繪制到窗口上。我們運(yùn)行程序,然后使用鼠標(biāo)拖出一個(gè)矩形,發(fā)現(xiàn)出現(xiàn)了很多重影,效果如下圖所示。 為什么會出現(xiàn)這種現(xiàn)象呢?大家可以嘗試分別快速拖動鼠標(biāo)和慢速拖動鼠標(biāo)來繪制矩形,結(jié)果會發(fā)現(xiàn),拖動速度越快,重影越少。其實(shí),在我們拖動鼠標(biāo)的過程中,屏幕已經(jīng)刷新了很多次,也可以理解為paintEvent()函數(shù)執(zhí)行了多次,每執(zhí)行一次就會繪制一個(gè)矩形。知道了原因,就有方法來避免這個(gè)問題發(fā)生了。 二、雙緩沖繪圖 1.我們再添加一個(gè)輔助畫布,如果正在繪圖,也就是鼠標(biāo)按鍵還沒有釋放的時(shí)候,就在這個(gè)輔助畫布上繪圖,只有當(dāng)鼠標(biāo)按鍵釋放的時(shí)候,才在真正的畫布上繪圖。 首先在dialog.h文件中添加兩個(gè)私有變量: QPixmap?tempPix;?//輔助畫布 bool?isDrawing;? ?//標(biāo)志是否正在繪圖 然后到dialog.cpp的構(gòu)造函數(shù)中對變量進(jìn)行初始化: isDrawing?=?false; 下面再更改paintEvent()函數(shù): 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中的內(nèi)容復(fù)制到tempPix中,保證以前的內(nèi)容不消失 ? ?? ??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); ? ??} } 下面還需要更改鼠標(biāo)按下事件處理函數(shù)和鼠標(biāo)釋放事件處理函數(shù)的內(nèi)容: void?Dialog::mousePressEvent(QMouseEvent?*event) { ? ??if(event->button()==Qt::LeftButton)?//鼠標(biāo)左鍵按下 ? ??{ ? ?? ??lastPoint?=?event->pos(); ? ?? ??isDrawing?=?true;? ?//正在繪圖 ? ??} } void?Dialog::mouseReleaseEvent(QMouseEvent?*event) { ? ??if(event->button()?==?Qt::LeftButton)?//鼠標(biāo)左鍵釋放 ? ??{ ? ?? ??endPoint?=?event->pos(); ? ?? ??isDrawing?=?false;? ??//結(jié)束繪圖 ? ?? ??update(); ? ??} } 當(dāng)鼠標(biāo)左鍵按下時(shí)我們開始標(biāo)記正在繪圖,當(dāng)按鍵釋放時(shí)我們?nèi)∠诶L圖的標(biāo)記。現(xiàn)在運(yùn)行程序,已經(jīng)可以實(shí)現(xiàn)正常的繪圖了。效果如下圖所示。 2.雙緩沖繪圖 根據(jù)這個(gè)例子所使用的技巧,我們引出所謂的雙緩沖繪圖的概念。雙緩沖(double-buffers)繪圖,就是在進(jìn)行繪制時(shí),先將所有內(nèi)容都繪制到一個(gè)繪圖設(shè)備(如QPixmap)上,然后再將整個(gè)圖像繪制到部件上顯示出來。使用雙緩沖繪圖可以避免顯示時(shí)的閃爍現(xiàn)象。從Qt 4.0開始,QWidget部件的所有繪制都自動使用了雙緩沖,所以一般沒有必要在paintEvent()函數(shù)中使用雙緩沖代碼來避免閃爍。 雖然在一般的繪圖中無需手動使用雙緩沖繪圖,不過要想實(shí)現(xiàn)一些繪圖效果,還是要借助于雙緩沖的概念。比如這個(gè)程序里,我們要實(shí)現(xiàn)使用鼠標(biāo)在界面上繪制一個(gè)任意大小的矩形。這里需要兩張畫布,它們都是QPixmap實(shí)例,其中一個(gè)tempPix用來作為臨時(shí)緩沖區(qū),當(dāng)鼠標(biāo)正在拖動矩形進(jìn)行繪制時(shí),將內(nèi)容先繪制到tempPix上,然后將tempPix繪制到界面上;而另一個(gè)pix作為緩沖區(qū),用來保存已經(jīng)完成的繪制。當(dāng)松開鼠標(biāo)完成矩形的繪制后,則將tempPix的內(nèi)容復(fù)制到pix上。為了繪制時(shí)不顯示拖影,而且保證以前繪制的內(nèi)容不消失,那么在移動鼠標(biāo)過程中,每繪制一次,都要在繪制這個(gè)矩形的原來的圖像上進(jìn)行繪制,所以需要在每次繪制tempPix之前,先將pix的內(nèi)容復(fù)制到tempPix上。因?yàn)檫@里有兩個(gè)QPixmap對象,也可以說有兩個(gè)緩沖區(qū),所以稱之為雙緩沖繪圖。 結(jié)語 ? ??對于Qt基本繪圖的內(nèi)容,我們就講到這里,如果大家還想更加系統(tǒng)深入的學(xué)習(xí)這些基礎(chǔ)知識,可以參考《Qt Creator快速入門》的第10章。從下一節(jié)開始,我們將簡單介紹一下Qt中得圖形視圖框架。 涉及到的源碼:??painter_3.zip? |
總結(jié)
以上是生活随笔為你收集整理的[Qt教程] 第18篇 2D绘图(八)双缓冲绘图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Qt教程] 第17篇 2D绘图(七)涂
- 下一篇: [Qt教程] 第19篇 2D绘图(九)图