欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Qt 鼠標/觸屏繪制平滑曲線(支持矢量/非矢量方式)

 更新時間:2020年04月08日 09:27:10   作者:luoyayun361  
這篇文章主要介紹了Qt 鼠標/觸屏繪制平滑曲線(支持矢量/非矢量方式),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

Qt通過鼠標或者觸屏,實時繪制平滑曲線,通常有兩種方式實現(xiàn):矢量繪圖和非矢量繪圖,這兩種畫線方式從實現(xiàn)上有些不同,其原理也不太一樣,稍后會做詳細介紹。而鼠標或者觸屏畫線也不大一樣,通常如果只實現(xiàn)鼠標畫線的話,那么只需要重新實現(xiàn)鼠標事件即可(mousePressEvent、mouseMoveEvent、mouseReleaseEvent),而要在觸控屏上畫線,如果需要支持多點畫線的話,就必須處理QTouchEvent事件才行,但是如果觸屏上只支持單點畫線,那也可以直接實現(xiàn)鼠標事件,因為第一個觸點的事件會同時進入到QTouchEvent和Mouse事件中。QTouchEvent中可以區(qū)分出多點時每個觸點的id,通過id進行區(qū)分每個點的數(shù)據(jù)。

通常情況下,為了提升繪圖效率,要實現(xiàn)這種繪圖的功能,都是用QGraphics體系來完成,因為QGraphics刷新機制和QWidget不太一樣,它可以做區(qū)域刷新,這樣能保證效率更高,特別是針對一些分辨率較高的設(shè)備,就很明顯了。具體這兩個體系間的區(qū)別就不在這里進行描述。

所以,接下來為了演示矢量和非矢量畫圖方式,我們在QGraphics體系中實現(xiàn)一個簡單的畫板程序。注重畫線效率,保證線條平滑無折線,無鋸齒,支持多點畫線。

效果圖

先開看看非矢量繪圖的效果:

再看矢量繪圖效果:

二者區(qū)別

通過上面的兩個圖對比,相信大家已經(jīng)看出了一些區(qū)別。我們再詳細介紹一下這兩者的區(qū)別。

非矢量繪圖

  • 優(yōu)點:速度快。非矢量繪圖原理是直接在一張圖片上進行繪制,其渲染速度很快,即便是畫了很多線條, 也不會有卡頓的效果,擦除時同樣很快。
  • 缺點:縮放失真。由于非矢量繪圖是在圖片上渲染,當縮放圖片時,會導(dǎo)致線條模糊不清晰,如果只是小范圍的縮放還能接受,無限縮放的話就會很明顯了。

矢量繪圖

  • 優(yōu)點:無限縮放,不失真。矢量繪圖是將點數(shù)據(jù)繪制生成一個單獨的對象,當進行縮放的時候,會重新進行渲染,所以矢量繪圖的方式不會導(dǎo)致圖像失真。
  • 缺點:線條多時會卡頓,擦除尤其明顯。由于矢量繪圖是生成一個單獨的對象,所以當畫線多的情況下,會觸發(fā)所有有交集的對象進行刷新,擦除的時候,會去計算線條之間的交集并做刪減,這個過程會很慢,并且會將整個對象item進行刷新,所以卡頓明顯(上述效果圖就可以看出來了)。

通過以上兩者的優(yōu)缺點對比,根據(jù)實際需要進行選擇實際的畫線模式。

解決實時繪圖折線問題

折線效果:


可以看到上述畫線有很明顯的折線,線條不平滑。

通常繪制這種線條,第一反應(yīng)想到的是講兩個點直接連接起來行成一條直線,但是,由于兩點之間距離比較大,特別是觸控屏,點與點之間并不是很密集,因為上層應(yīng)用在主線程渲染的時候,系統(tǒng)會自動丟棄一些數(shù)據(jù)點,即便是底層上報的點很多,上層應(yīng)用接收到的點也會減少,所以不能直接用連接兩點的方式來實現(xiàn)。

那么,該怎么解決呢?
繪制貝塞爾曲線。

在move的過程中實時生成貝塞爾曲線path,這樣就能保證線條無折線。QPainterPath支持貝塞爾曲線繪制,參加以下函數(shù):

void QPainterPath::quadTo(const QPointF &c, const QPointF &endPoint)

Adds a quadratic Bezier curve between the current position and the given endPoint with the control point specified by c.
After the curve is added, the current point is updated to be at the end point of the curve.

注意該函數(shù),第一個參數(shù)是控制點,該點就是上一個觸控點,而第二個參數(shù)是前一個點和當前點的中點,也就是兩個點坐標加起來除以2.

非矢量繪圖實現(xiàn)方式

所謂的非矢量繪圖,就是在一張圖片上進行繪制,然后將圖片渲染到QGraphicsItem的背景上面,前面我們已經(jīng)提到,該方式渲染速度非??欤瑹o論畫多少線條都不會影響速度,而擦除功能只需要按照同樣的方式繪制背景色即可。

但是該方式在縮放過后圖片會有些模糊,如果只是小范圍的縮放還好,無限縮放就需要用到矢量繪圖的方式了。

矢量繪圖實現(xiàn)方式

相比之下,矢量繪圖就會稍微麻煩一點,所謂矢量繪圖,就是將path曲線直接生成一個獨立的對象,將該對象添加到scene中,這種模式下會有一個缺陷,就是當畫線較多的情況下,刷新會比較慢,因為會導(dǎo)致整條曲線(只要有交集)刷新,從而導(dǎo)致卡頓的效果,并且在擦除時,需要實時計算擦除的path與實際線條path的交集,然后進行計算,減去擦除的path,這個過程是最耗時的,并且也會引發(fā)整個item刷新。前面寫過文章介紹QGraphics體系的刷新機制,在這里

由于矢量繪圖需要生成一條完整的path進行繪制,而觸控點是在move事件中取到,如果實時生成貝塞爾曲線去繪制,那么當一直不松手的畫一條線時,畫到后面將會越來越慢,因為動態(tài)生成path后會重新將整條path進行渲染,隨著線條越長,那么刷新區(qū)域就會越大,這就會導(dǎo)致刷新變慢而延遲變高。那么怎么解決這個問題呢?答案就是通過雙緩沖的方式來實現(xiàn)繪制。

雙緩沖繪圖

上面介紹到,通過非矢量繪圖的方式,速度會非???,那么雙緩沖繪圖就是要結(jié)合非矢量來進行,其原理就是:在press事件中生成一條path,接著move中動態(tài)增加這條path,然后在臨時層上進行非矢量繪圖,這時候繪制的速度會非???,最后在release事件中將完整的path繪制成矢量圖,然后將臨時層畫線清空。基本原理就是這樣。

雙緩沖繪圖方式,在繪制過程中是通過非矢量的方式在臨時層進行,release后生成完整的矢量path,這種方式速度會非??欤⑶抑苯永L制完整的一條path不會有鋸齒。所以這是最佳選擇。

代碼太多,就不附代碼了。

到此這篇關(guān)于Qt 鼠標/觸屏繪制平滑曲線(支持矢量/非矢量方式)的文章就介紹到這了,更多相關(guān)Qt 繪制平滑曲線內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++?shared_ptr智能指針reset()使用示例詳解

    C++?shared_ptr智能指針reset()使用示例詳解

    這篇文章主要為大家介紹了C++?shared_ptr智能指針reset()使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • C++ Virtual關(guān)鍵字的具體使用

    C++ Virtual關(guān)鍵字的具體使用

    這篇文章主要介紹了C++ Virtual關(guān)鍵字的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 論C++的lambda是函數(shù)還是對象

    論C++的lambda是函數(shù)還是對象

    這篇文章主要介紹了論C++的lambda是函數(shù)還是對象,對于有捕獲的lambda,其等價于對象。對于沒有任何捕獲的lambda,其等價于函數(shù),下面來看看具體的相關(guān)內(nèi)容,需要的朋友可以參考一下
    2022-02-02
  • C++實現(xiàn)打印1到最大的n位數(shù)

    C++實現(xiàn)打印1到最大的n位數(shù)

    這篇文章主要介紹了C++實現(xiàn)打印1到最大的n位數(shù),并分析了實現(xiàn)代碼中語句的跳轉(zhuǎn)技巧,需要的朋友可以參考下
    2014-09-09
  • C++空類詳解

    C++空類詳解

    以下是對C++中的空類進行了詳細的介紹,需要的朋友可以過來參考下
    2013-09-09
  • C語言簡明介紹常見關(guān)鍵字的用法

    C語言簡明介紹常見關(guān)鍵字的用法

    關(guān)鍵字是C語言非常重要的一部分,熟練的掌握和使用關(guān)鍵字有助于我們更加熟悉了解C語言,同時C語言的關(guān)鍵字也是面試筆試中??嫉膬?nèi)容。C語言的關(guān)鍵字共有32個,但并不是每個關(guān)鍵字都有坑,本篇文章將通過理論聯(lián)系實際的方式為大家講解C語言中易混易錯以及??嫉囊恍╆P(guān)鍵字
    2022-06-06
  • C語言三子棋小游戲的實現(xiàn)

    C語言三子棋小游戲的實現(xiàn)

    這篇文章主要為大家詳細介紹了C語言三子棋小游戲的實現(xiàn),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • C語言實現(xiàn)CRC校驗算法的示例詳解

    C語言實現(xiàn)CRC校驗算法的示例詳解

    CRC(Cyclic Redundancy Check,循環(huán)冗余校驗)是一種常用的錯誤檢測技術(shù),用于驗證數(shù)據(jù)在傳輸或存儲過程中是否發(fā)生了錯誤,本文主要介紹了C語言如何實現(xiàn)CRC校驗算法,需要的可以參考一下
    2023-08-08
  • C++使用模板實現(xiàn)單鏈表

    C++使用模板實現(xiàn)單鏈表

    這篇文章主要為大家詳細介紹了C++使用模板實現(xiàn)單鏈表,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • C#將Unicode編碼轉(zhuǎn)換為漢字字符串的簡單方法

    C#將Unicode編碼轉(zhuǎn)換為漢字字符串的簡單方法

    下面小編就為大家?guī)硪黄狢#將Unicode編碼轉(zhuǎn)換為漢字字符串的簡單方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01

最新評論