[Qt教程] 第18篇 2D绘图(八)双缓冲绘图
生活随笔
收集整理的這篇文章主要介紹了
[Qt教程] 第18篇 2D绘图(八)双缓冲绘图
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
[Qt教程]?第18篇 2D繪圖(八)雙緩沖繪圖
??|?查看: 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兩個點來確定要繪制的矩形的起點、寬和高的。運行程序,用鼠標拖出一個矩形,效果如下圖所示。 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); } 這里就是將圖形先繪制在了畫布上,然后將畫布繪制到窗口上。我們運行程序,然后使用鼠標拖出一個矩形,發現出現了很多重影,效果如下圖所示。 為什么會出現這種現象呢?大家可以嘗試分別快速拖動鼠標和慢速拖動鼠標來繪制矩形,結果會發現,拖動速度越快,重影越少。其實,在我們拖動鼠標的過程中,屏幕已經刷新了很多次,也可以理解為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(); ? ??} } 當鼠標左鍵按下時我們開始標記正在繪圖,當按鍵釋放時我們取消正在繪圖的標記。現在運行程序,已經可以實現正常的繪圖了。效果如下圖所示。 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? |
總結
以上是生活随笔為你收集整理的[Qt教程] 第18篇 2D绘图(八)双缓冲绘图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Qt教程] 第17篇 2D绘图(七)涂
- 下一篇: [Qt教程] 第19篇 2D绘图(九)图