Qt中PaintEvent繪制實時波形圖的實現(xiàn)示例_第1頁
Qt中PaintEvent繪制實時波形圖的實現(xiàn)示例_第2頁
Qt中PaintEvent繪制實時波形圖的實現(xiàn)示例_第3頁
Qt中PaintEvent繪制實時波形圖的實現(xiàn)示例_第4頁
Qt中PaintEvent繪制實時波形圖的實現(xiàn)示例_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第Qt中PaintEvent繪制實時波形圖的實現(xiàn)示例目錄繪制思路1:接收硬件傳入的數(shù)據(jù)2:定時器動態(tài)刷新頁面3:真實數(shù)據(jù)處理第一步:每進行一次數(shù)據(jù)更新,都需要剔除超時顯示數(shù)據(jù)。第二步:篩查有效數(shù)據(jù),并記錄4:圖形繪制上一篇文章講述了如何使用控件進行波形圖繪制,雖然很方便,但是也有一些無法避免的問題,比如說:動態(tài)繪制圖形時,想要流暢的進行波動,就必須按照特定的時間實時更換數(shù)據(jù)。

接來下,我們采用在paintEvent中繪制的方式進行實時波形圖繪制,首先,我們先展示下顯示效果吧!

數(shù)據(jù)來源依舊是硬件傳入的實時數(shù)據(jù),如下:

[0,3,5,8,10,13,15,18,20,23,25,28,26,23,20,16,13,11,9,6,4,3,0]

其實有些人看到這里會說,數(shù)據(jù)都有了直接畫出來不就可以了嗎?

在我們實際應(yīng)用過程中,這些硬件上傳的數(shù)據(jù)不是一次性傳出的,而是取決于你操作硬件的頻率以及事件決定的。所以說,想要一次性拿出一整條數(shù)據(jù)來繪制,這個時機已經(jīng)晚了。

那么,我們該如何使用paintEvent實時繪制出波形圖呢?接下來就來講解下我的思路吧,如果覺得我的思路比較繁瑣,大家也可以提出來,我也學習下,彌補下自己的不足。

繪制思路

1:接收硬件傳入的數(shù)據(jù)

這里使用了SetRealTimeDepthData(stDepthDatastData);意思是:設(shè)置實時深度數(shù)據(jù)值。

參數(shù)穿入的是一個結(jié)構(gòu)體,在使用這個函數(shù)之前我已經(jīng)將數(shù)據(jù)做了簡單的處理,包括了深度方向設(shè)置。

比如:當深度逐漸變大時,深度方向div是正數(shù),當深度逐漸減小時,深度方向div是負數(shù)。

下面,我展示下我實際處理后的數(shù)據(jù)值

對于這些真實數(shù)據(jù)我設(shè)定了一個結(jié)構(gòu)體,用于存儲數(shù)據(jù)時間、深度方向以及具體深度值

structDrawingEffectivePress

intnDiv;//深度方向

intnDepth;//深度值

DWORDdwTime;//記錄當前真實數(shù)據(jù)的時間

DrawingEffectivePress():nDiv(0),nDepth(0),dwTime(0){}

}

SetRealTimeDepthData具體實現(xiàn),如下:

voidQDrawingWaveform::SetRealTimeDepthData(stDepthDatastData)

std::lock_guardstd::mutexlck(m_dataMutex);//加鎖進行數(shù)據(jù)操作

DrawingEffectivePressstDepth;

stDepth.nDiv=stData.nDiv=01:-1;

stDepth.nDepth=stData.nDepth;

stDepth.dwTime=GetTickCont();

m_vetDepth.push_back(stDepth);

}

代碼講解:

有上述圖片的真實數(shù)據(jù)來看,深度的方位是逐漸遞增的,那么在程序中我們采用了1和-1的方式表示,正方向時都是用1來表示,負方向時都是用-1來表示。

每有一條真實數(shù)據(jù)時,都需要記錄當前真實數(shù)據(jù)的具體時間,用于繪制實時的動態(tài)走向。

2:定時器動態(tài)刷新頁面

設(shè)定定時器每40毫秒刷新一次頁面:

#defineTimeInterval40//定時器時間間隔

定時器啟動m_nTimerId=startTimer(TimeInterval);

3:真實數(shù)據(jù)處理

這是我們繪制的一個重點,也是比較麻煩的一部分了。

與硬件打過交道的友友們都知道,硬件數(shù)據(jù)的不穩(wěn)定性,有些時候看著數(shù)據(jù)的走向是朝下的,因為手動操作緣故,偶爾會有一些浮動的數(shù)據(jù),這些數(shù)據(jù)需要篩除,在傳入數(shù)據(jù)之前我已經(jīng)做了處理,這個問題在這篇文章中是不存在的。

使用m_vetDepth存儲了實際的深度數(shù)據(jù)值。

std::vectorDrawingEffectivePressm_vetDepth;

第一步:每進行一次數(shù)據(jù)更新,都需要剔除超時顯示數(shù)據(jù)。

什么叫做超時顯示數(shù)據(jù)?

根據(jù)文章一開篇的動畫可以看出,波形圖一邊進行繪制操作,一邊向左移動。

在移動過程中,肯定會移出左邊界,那么也就代表了當前的圖形不需要展示。對此,我們就需要在每次更新數(shù)據(jù)時,判斷有哪些數(shù)據(jù)是已經(jīng)超過顯示范圍的,需要進行剔除了。

那么,到這里也就遇到了另外一個問題,我們剔除的數(shù)據(jù)是在m_vetDepth中存儲的數(shù)據(jù)嗎?

答案是的,但是為了邏輯簡單操作,我們需要重新定義一個結(jié)構(gòu)體,當前結(jié)構(gòu)體主要用來做已經(jīng)繪制成圖形的點的記錄。

std::vectorDrawingEffectivePressm_vetEffectiveDepth;

在當前容器中存儲的數(shù)據(jù)一定是具體特定標識的,也就是波形圖的拐點數(shù)據(jù),一個完整波形的最低點以及最高點。

當我們進行實際繪圖時,也是取m_vetEffectiveDepth中的數(shù)據(jù),保證了數(shù)據(jù)邏輯簡單性。

現(xiàn)在,我們先來看一看剔除超時數(shù)據(jù)的實際代碼,如下:

voidQDrawingWaveform::DeletingTimeoutData()

DWORDdwCurrentTime=GetTickCount();//當前時間

std::vectorDrawingEffectivePress::iteratoritvet=m_vetEffectivePress.begin();

for(itvet;itvet!=m_vetEffectivePress.end();)

DrawingEffectivePressstPoint=*itvet;

if((dwCurrentTime-stPoint.dwPressTime)m_nSingShowTime)

//超過界面展示范圍,剔除數(shù)據(jù)

itvet=m_vetEffectivePress.erase(itvet++);

else

itvet++;

}

代碼解析:實時獲取最新時間,每次都判斷存儲的硬件操作時間與設(shè)定的最大值(m_nSingShowTime)進行比較。

當超過設(shè)定的時間時,說明圖形已經(jīng)消失在界面上了,就需要剔除數(shù)據(jù)。

第二步:篩查有效數(shù)據(jù),并記錄

上一步驟是剔除超時數(shù)據(jù),那么我們該如何存儲這些有效數(shù)據(jù)到m_vetEffectivePress容器中呢?

思路:

1:默認容器中存儲前兩條數(shù)據(jù)。

2:當后續(xù)數(shù)據(jù)來時,需要與上一條數(shù)據(jù)進行判別。

2.1:如果方向一致,說明深度一直在遞增或者是遞減,直接替換最后一會有效數(shù)據(jù)的值即可。

2.2:如果方向不一致,說明深度值發(fā)生了變換,可能由向下變成了向上;也可能由向上變成了向下。不再做數(shù)據(jù)替換操作,而是插入一條新數(shù)據(jù)。

3:操作一條數(shù)據(jù)后,進行數(shù)據(jù)刪除。

將上述思路轉(zhuǎn)變成代碼,如下:

std::vectorDrawingEffectivePress::iteratoritvet=m_vetPress.begin()

for(itvet;itvet!=m_vetPress.end();)

DrawingEffectivePressstPoint=*itvet;

DrawingEffectivePressstPress;

stPress.dwTime=stPoint.dwTime;

stPress.nDiv=stPoint.nDiv;

stPress.nDepth=stPoint.nDepth;

intnsize=m_vetEffectivePress.size();

if(nsize2)

m_vetEffectivePress.push_back(stPress);

else

//如果當前數(shù)據(jù)stPoint與m_vetEffectivePress的最后一位的拐點一致,

//剔除掉m_vetEffectivePress的最后一位,存儲成最新數(shù)據(jù)

if(m_vetEffectivePress[nsize-1].nDiv==stPoint.nDiv)

//更新m_vetEffectivePress的最后一位

m_vetEffectivePress[nsize-1]=stPress;

else

//存儲的最后一位的拐點與當前數(shù)值不一致時,直接存儲

m_vetEffectivePress.push_back(stPress);

itvet=m_vetPress.erase(itvet++);

}

4:圖形繪制

經(jīng)過上述數(shù)據(jù)處理后,我們可以直接在panitEvent中直接繪制出m_vetEffectivePress圖形了。

實際代碼效果如下:

QPainterpainter(this);

painter.setRenderHint(QPainter::Antialiasing);//抗鋸齒

QPolygonpolygon;

for(inti=0;im_vetEffectivePress.size();i++)

DrawingEffectivePressstPoint=m_vetEffectivePress[i];

intnX=this-CalcRealPointX(stPoint.dwPressTime);

intnY=this-CalcRealPointY(stPoint.nDepth);

polygonQPoint(nX,nY);

painter.drawPolyline(polygon);

代碼解析:根據(jù)實際數(shù)據(jù)的操作時間以及具體的深度值,可以確定波形圖的x軸與y軸了。

根據(jù)時間的變化,就可以讓圖形看起來是一種動起來的效果。

CalcRealPointX實際處理

//TODO:計算,實際的x軸坐標

DWORDdwCurrent=GetTickCount();

intnRectRight=rect().right();

intnMoveOriginal=dwDepthTime-dwCurrent;

doubledMoveLen=nMoveOriginal/8;

intnX=nRectRight+dMoveLen;

returnnX;

代碼解析:實時獲取當前繪制時間,并減去結(jié)構(gòu)體中存儲的深度時間,設(shè)置移動長度(dwMoveOriginal)。

因為要向左偏移,所以,每次用窗口的右側(cè)區(qū)域減去就可以了。

注意:我這里使用的是+,因為我計算得出的偏移長度一定是一個負值。實時時間一定會比實際深度時間大,所以結(jié)果肯定是一個負值。

到這里,我們的實時圖形繪制算是完成了80%了,想要繪制出連續(xù)的實時深度值圖形就可以實現(xiàn)了。

為什么說是80%呢?

因為還有一個我們需要考慮的問題,當不是連續(xù)數(shù)據(jù)獲取時,使用QPolygon繪制圖形時,就會出現(xiàn)以下效果:

當我們不是連續(xù)繪制深度值時,間隔一定時間后,再進行繪圖時,就

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論