您好,登錄后才能下訂單哦!
前言
Qt通過鼠標或者觸屏,實時繪制平滑曲線,通常有兩種方式實現:矢量繪圖和非矢量繪圖,這兩種畫線方式從實現上有些不同,其原理也不太一樣,稍后會做詳細介紹。而鼠標或者觸屏畫線也不大一樣,通常如果只實現鼠標畫線的話,那么只需要重新實現鼠標事件即可(mousePressEvent、mouseMoveEvent、mouseReleaseEvent),而要在觸控屏上畫線,如果需要支持多點畫線的話,就必須處理QTouchEvent事件才行,但是如果觸屏上只支持單點畫線,那也可以直接實現鼠標事件,因為第一個觸點的事件會同時進入到QTouchEvent和Mouse事件中。QTouchEvent中可以區分出多點時每個觸點的id,通過id進行區分每個點的數據。
通常情況下,為了提升繪圖效率,要實現這種繪圖的功能,都是用QGraphics體系來完成,因為QGraphics刷新機制和QWidget不太一樣,它可以做區域刷新,這樣能保證效率更高,特別是針對一些分辨率較高的設備,就很明顯了。具體這兩個體系間的區別就不在這里進行描述。
所以,接下來為了演示矢量和非矢量畫圖方式,我們在QGraphics體系中實現一個簡單的畫板程序。注重畫線效率,保證線條平滑無折線,無鋸齒,支持多點畫線。
效果圖
先開看看非矢量繪圖的效果:
再看矢量繪圖效果:
二者區別
通過上面的兩個圖對比,相信大家已經看出了一些區別。我們再詳細介紹一下這兩者的區別。
非矢量繪圖
矢量繪圖
通過以上兩者的優缺點對比,根據實際需要進行選擇實際的畫線模式。
解決實時繪圖折線問題
折線效果:
可以看到上述畫線有很明顯的折線,線條不平滑。
通常繪制這種線條,第一反應想到的是講兩個點直接連接起來行成一條直線,但是,由于兩點之間距離比較大,特別是觸控屏,點與點之間并不是很密集,因為上層應用在主線程渲染的時候,系統會自動丟棄一些數據點,即便是底層上報的點很多,上層應用接收到的點也會減少,所以不能直接用連接兩點的方式來實現。
那么,該怎么解決呢?
繪制貝塞爾曲線。
在move的過程中實時生成貝塞爾曲線path,這樣就能保證線條無折線。QPainterPath支持貝塞爾曲線繪制,參加以下函數:
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.
注意該函數,第一個參數是控制點,該點就是上一個觸控點,而第二個參數是前一個點和當前點的中點,也就是兩個點坐標加起來除以2.
非矢量繪圖實現方式
所謂的非矢量繪圖,就是在一張圖片上進行繪制,然后將圖片渲染到QGraphicsItem的背景上面,前面我們已經提到,該方式渲染速度非常快,無論畫多少線條都不會影響速度,而擦除功能只需要按照同樣的方式繪制背景色即可。
但是該方式在縮放過后圖片會有些模糊,如果只是小范圍的縮放還好,無限縮放就需要用到矢量繪圖的方式了。
矢量繪圖實現方式
相比之下,矢量繪圖就會稍微麻煩一點,所謂矢量繪圖,就是將path曲線直接生成一個獨立的對象,將該對象添加到scene中,這種模式下會有一個缺陷,就是當畫線較多的情況下,刷新會比較慢,因為會導致整條曲線(只要有交集)刷新,從而導致卡頓的效果,并且在擦除時,需要實時計算擦除的path與實際線條path的交集,然后進行計算,減去擦除的path,這個過程是最耗時的,并且也會引發整個item刷新。前面寫過文章介紹QGraphics體系的刷新機制,在這里
由于矢量繪圖需要生成一條完整的path進行繪制,而觸控點是在move事件中取到,如果實時生成貝塞爾曲線去繪制,那么當一直不松手的畫一條線時,畫到后面將會越來越慢,因為動態生成path后會重新將整條path進行渲染,隨著線條越長,那么刷新區域就會越大,這就會導致刷新變慢而延遲變高。那么怎么解決這個問題呢?答案就是通過雙緩沖的方式來實現繪制。
雙緩沖繪圖
上面介紹到,通過非矢量繪圖的方式,速度會非常快,那么雙緩沖繪圖就是要結合非矢量來進行,其原理就是:在press事件中生成一條path,接著move中動態增加這條path,然后在臨時層上進行非矢量繪圖,這時候繪制的速度會非常快,最后在release事件中將完整的path繪制成矢量圖,然后將臨時層畫線清空。基本原理就是這樣。
雙緩沖繪圖方式,在繪制過程中是通過非矢量的方式在臨時層進行,release后生成完整的矢量path,這種方式速度會非常快,并且直接繪制完整的一條path不會有鋸齒。所以這是最佳選擇。
代碼太多,就不附代碼了。
到此這篇關于Qt 鼠標/觸屏繪制平滑曲線(支持矢量/非矢量方式)的文章就介紹到這了,更多相關Qt 繪制平滑曲線內容請搜索億速云以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持億速云!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。