日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【Qt】2D绘图之双缓冲绘图

發(fā)布時(shí)間:2024/4/24 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Qt】2D绘图之双缓冲绘图 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

00. 目錄

文章目錄

    • 00. 目錄
    • 01. 概述
    • 02. 開發(fā)環(huán)境
    • 03. 繪制矩形
    • 04. 雙緩沖繪圖
    • 05. 附錄

01. 概述

所謂的雙緩沖繪圖的概念。雙緩沖(double-buffers)繪圖,就是在進(jìn)行繪制時(shí),先將所有內(nèi)容都繪制到一個(gè)繪圖設(shè)備(如QPixmap)上,然后再將整個(gè)圖像繪制到部件上顯示出來(lái)。使用雙緩沖繪圖可以避免顯示時(shí)的閃爍現(xiàn)象。從Qt 4.0開始,QWidget部件的所有繪制都自動(dòng)使用了雙緩沖,所以一般沒有必要在paintEvent()函數(shù)中使用雙緩沖代碼來(lái)避免閃爍。

? 雖然在一般的繪圖中無(wú)需手動(dòng)使用雙緩沖繪圖,不過要想實(shí)現(xiàn)一些繪圖效果,還是要借助于雙緩沖的概念。比如這個(gè)程序里,我們要實(shí)現(xiàn)使用鼠標(biāo)在界面上繪制一個(gè)任意大小的矩形。這里需要兩張畫布,它們都是QPixmap實(shí)例,其中一個(gè)tempPix用來(lái)作為臨時(shí)緩沖區(qū),當(dāng)鼠標(biāo)正在拖動(dòng)矩形進(jìn)行繪制時(shí),將內(nèi)容先繪制到tempPix上,然后將tempPix繪制到界面上;而另一個(gè)pix作為緩沖區(qū),用來(lái)保存已經(jīng)完成的繪制。當(dāng)松開鼠標(biāo)完成矩形的繪制后,則將tempPix的內(nèi)容復(fù)制到pix上。為了繪制時(shí)不顯示拖影,而且保證以前繪制的內(nèi)容不消失,那么在移動(dòng)鼠標(biāo)過程中,每繪制一次,都要在繪制這個(gè)矩形的原來(lái)的圖像上進(jìn)行繪制,所以需要在每次繪制tempPix之前,先將pix的內(nèi)容復(fù)制到tempPix上。因?yàn)檫@里有兩個(gè)QPixmap對(duì)象,也可以說(shuō)有兩個(gè)緩沖區(qū),所以稱之為雙緩沖繪圖。

02. 開發(fā)環(huán)境

Windows系統(tǒng):Windows10

Qt版本:Qt5.15或者Qt6

03. 繪制矩形

3.1 在涂鴉板的程序的基礎(chǔ)之上繼續(xù)更改

//繪圖事件 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); }

運(yùn)行結(jié)果

3.2 上面已經(jīng)可以拖出一個(gè)矩形了,但是這樣直接在窗口上繪圖,以前畫的矩形是不能保存下來(lái)的。所以我們下面加入畫布,在畫布上進(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 p1(&pix);p1.drawRect(x, y, w, h);QPainter painter(this);painter.drawPixmap(0, 0, pix); }

這里就是將圖形先繪制在了畫布上,然后將畫布繪制到窗口上。我們運(yùn)行程序,然后使用鼠標(biāo)拖出一個(gè)矩形,發(fā)現(xiàn)出現(xiàn)了很多重影,效果如下圖所示。

大家可以嘗試分別快速拖動(dòng)鼠標(biāo)和慢速拖動(dòng)鼠標(biāo)來(lái)繪制矩形,結(jié)果會(huì)發(fā)現(xiàn),拖動(dòng)速度越快,重影越少。其實(shí),在我們拖動(dòng)鼠標(biāo)的過程中,屏幕已經(jīng)刷新了很多次,也可以理解為paintEvent()函數(shù)執(zhí)行了多次,每執(zhí)行一次就會(huì)繪制一個(gè)矩形。知道了原因,就可以想辦法來(lái)避免這個(gè)問題發(fā)生了。

04. 雙緩沖繪圖

4.1 我們?cè)偬砑右粋€(gè)輔助畫布,如果正在繪圖,也就是鼠標(biāo)按鍵還沒有釋放的時(shí)候,就在這個(gè)輔助畫布上繪圖,只有當(dāng)鼠標(biāo)按鍵釋放的時(shí)候,才在真正的畫布上繪圖。

首先在dialog.h文件中添加兩個(gè)私有變量

//臨時(shí)畫布QPixmap tmpPix;//標(biāo)志是否正在繪圖bool isDrawing;

在構(gòu)造函數(shù)初始化

isDrawing = false;

4.2 更改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);//如果正在繪圖,就在臨時(shí)畫布上面繪制if (isDrawing){tmpPix = pix;QPainter p1(&tmpPix);p1.drawRect(x, y, w, h);painter.drawPixmap(0, 0, tmpPix);}else{QPainter p1(&pix);p1.drawRect(x, y, w, h);painter.drawPixmap(0, 0, pix);} }

4.3 更改鼠標(biāo)按下事件處理函數(shù)和鼠標(biāo)釋放事件處理函數(shù)的內(nèi)容:

//鼠標(biāo)左鍵按下事件 void Dialog::mousePressEvent(QMouseEvent *e) {if (e->button() == Qt::LeftButton){lastPoint = e->pos();//正在繪圖isDrawing = true;}endPoint = lastPoint; }//鼠標(biāo)釋放事件 void Dialog::mouseReleaseEvent(QMouseEvent *e) {if (e->button() == Qt::LeftButton){endPoint = e->pos();//結(jié)束繪圖isDrawing = false;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)正常的繪圖了。效果如下圖所示。

05. 附錄

源碼下載:【Qt】2D繪圖之雙緩沖繪圖.rar

總結(jié)

以上是生活随笔為你收集整理的【Qt】2D绘图之双缓冲绘图的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。