vc2010 MFC下如何绘制频谱图??

vc2010 MFC下如何绘制频谱图??,第1张

C++ GUI 绘图控件目录

MFC(VC)

VS2010 使用TeeChart绘图控件 - 之一 - 控件和类的导入

VS2010 使用TeeChart绘图控件 - 之二 - 绘制图形(折线图,柱状图)

TeeChart绘图控件 - 之三 - 提高绘图的效率

MFC下好用的高速绘图控件-(Hight-Speed Charting)

绘制动态曲线

Qt

qt超强精美绘图控件 - QCustomPlot一览

qt超强绘图控件qwt - 安装及配置

对于任何绘图控件,都可以实现动态绘图,其原则是:控件只负责绘图,若想曲线动,就让数据动,就像看电影一样,电影是由一帧一帧的静态图片组合起来的,在一定速度上刷新,静态图片就能动起来;和电影的原理一样,绘图控件能显示静态的曲线,想要它动起来,就让它频在一定时间刷新就可以了。

这就是动态绘图的实现原理。

实现动态曲线需要以下两个准备:

计时器Timer

数组左移

基于Timer的绘图

任何界面库都会有Timer这个实现,在MFC中时OnTimer消息,在Qt中是QTimer类,那种原理基本都一样,下面将以MFC(VC)为例进行说明。

Timer是消息级别最低的消息,它会保证其它级别高的消息优先执行,因此,就算数据大量刷新,也不会影响主线程的其它消息。

MFC生成OnTimer消息,消息响应函数如下:

[cpp] view plaincopy

void CTeeChartDlg::OnTimer(UINT_PTR nIDEvent)  

{  

    // TODO: 在此添加消息处理程序代码或调用默认值  

    CDialogEx::OnTimer(nIDEvent)  

}

绘图的实现就在这个消息响应函数里

如果让定时器设定为1秒触发,每一秒把旧数据去除,绘制新数据,就能看到不停变换的波形;对于趋势图,假如每秒有一个新数据,那么就在定长数组中,把数组所有数据整体左移,同时数组末端加入新数据。代码如下:

[cpp] view plaincopy

///   

/// \brief 左移数组  

/// \param ptr 数组指针  

/// \param data 新数值  

///  

void LeftMoveArray(double* ptr,size_t length,double data)  

{  

    for (size_t i=1i<length++i)  

    {  

        ptr[i-1] = ptr[i]  

    }  

    ptr[length-1] = data  

}

此函数把整个数组左移,然后新数据放置在数组最末端(右端)。

这样,数组就实现“向左运动”,把左移后的数组绘制,就能在绘图控件上发现其变化。

下面开始实现动态绘图(这里演示TeeChart的方法,附件里有HightSpeed-Chart CChartCtrl的方法):

[cpp] view plaincopy

void CTeeChartDlg::OnBnClickedButtonRuning()  

{  

    KillTimer(0)  

    ZeroMemory(&m_TeeChartArray,sizeof(double)*m_c_arrayLength)  

    for (size_t i=0i<m_c_arrayLength++i)  

    {  

        m_X[i] = i  

    }  

    m_count = m_c_arrayLength  

    CSeries chart_T = (CSeries)m_Chart.Series(0)  

    chart_T.Clear()  

    m_pLineSerie->ClearSerie()  

    SetTimer(0,1000,NULL)    

}

函数中几个成员变量的定义是:

[cpp] view plaincopy

double m_TeeChartArray[2096]  

double m_X[2096]  

unsigned int m_count  

const size_t m_c_arrayLength = 2096

m_TeeChartArray是需要绘制的数组的Y值,m_X是对应的x值,m_count是计数器,每绘制一次,个数加1,主要用于x轴

在timer中的实现如下:

void CTeeChartDlg::OnTimer(UINT_PTR nIDEvent)  

{  

    // TODO: 在此添加消息处理程序代码和/或调用默认值  

    if(0 == nIDEvent)  

    {  

        ++m_count  

        drawMoving()  

    }  

    CDialogEx::OnTimer(nIDEvent)  

}

在工控监测领域,经常需要动态绘制曲线,观察曲线的变化趋势,绘制波形图,绘制频谱等。在前面4讲中介绍了MFC经常用的TeeChart控件和Hight-Speed Chart Ctrl,这两个都是MFC绘图控件的经典(另外,在Qt中还有QwtPlot和QCustomPlot两大神器)。许多人问如何绘制动态变化的曲线,为此专门写下这篇文章。

C++ GUI 绘图控件目录

MFC(VC)

VS2010 使用TeeChart绘图控件 - 之一 - 控件和类的导入

VS2010 使用TeeChart绘图控件 - 之二 - 绘制图形(折线图,柱状图)

TeeChart绘图控件 - 之三 - 提高绘图的效率

MFC下好用的高速绘图控件-(Hight-Speed Charting)

绘制动态曲线

Qt

qt超强精美绘图控件 - QCustomPlot一览

qt超强绘图控件qwt - 安装及配置

   

对于任何绘图控件,都可以实现动态绘图,其原则是:控件只负责绘图,若想曲线动,就让数据动,就像看电影一样,电影是由一帧一帧的静态图片组合起来的,在一定速度上刷新,静态图片就能动起来;和电影的原理一样,绘图控件能显示静态的曲线,想要它动起来,就让它频在一定时间刷新就可以了。  

这就是动态绘图的实现原理。

实现动态曲线需要以下两个准备:

计时器Timer

数组左移

基于Timer的绘图

任何界面库都会有Timer这个实现,在MFC中时OnTimer消息,在Qt中是QTimer类,那种原理基本都一样,下面将以MFC(VC)为例进行说明。

Timer是消息级别最低的消息,它会保证其它级别高的消息优先执行,因此,就算数据大量刷新,也不会影响主线程的其它消息。

MFC生成OnTimer消息,消息响应函数如下:

void CTeeChartDlg::OnTimer(UINT_PTR nIDEvent){ // TODO: 在此添加消息处理程序代码或调用默认值 CDialogEx::OnTimer(nIDEvent)}

绘图的实现就在这个消息响应函数里

如果让定时器设定为1秒触发,每一秒把旧数据去除,绘制新数据,就能看到不停变换的波形;对于趋势图,假如每秒有一个新数据,那么就在定长数组中,把数组所有数据整体左移,同时数组末端加入新数据。代码如下:

/// /// \brief 左移数组/// \param ptr 数组指针/// \param data 新数值///void LeftMoveArray(double* ptr,size_t length,double data){ for (size_t i=1i<length++i) { ptr[i-1] = ptr[i] } ptr[length-1] = data}

此函数把整个数组左移,然后新数据放置在数组最末端(右端)。

这样,数组就实现“向左运动”,把左移后的数组绘制,就能在绘图控件上发现其变化。

下面开始实现动态绘图(这里演示TeeChart的方法,附件里有HightSpeed-Chart CChartCtrl的方法):

void CTeeChartDlg::OnBnClickedButtonRuning(){ KillTimer(0) ZeroMemory(&m_TeeChartArray,sizeof(double)*m_c_arrayLength) for (size_t i=0i<m_c_arrayLength++i) { m_X[i] = i } m_count = m_c_arrayLength CSeries chart_T = (CSeries)m_Chart.Series(0) chart_T.Clear() m_pLineSerie->ClearSerie() SetTimer(0,1000,NULL) }

函数中几个成员变量的定义是: double m_TeeChartArray[2096] double m_X[2096] unsigned int m_count const size_t m_c_arrayLength = 2096

m_TeeChartArray是需要绘制的数组的Y值,m_X是对应的x值,m_count是计数器,每绘制一次,个数加1,主要用于x轴

在timer中的实现如下:

void CTeeChartDlg::OnTimer(UINT_PTR nIDEvent){ // TODO: 在此添加消息处理程序代码和/或调用默认值 if(0 == nIDEvent) { ++m_count drawMoving() } CDialogEx::OnTimer(nIDEvent)}

drawMoving函数用于绘图,timer设定为1秒触发一次,这时就能看到每秒的变化,如果数据是以1秒为刷新周期,每一秒有个新数据,只需要把旧的数据向左移,新数据放到数组最右端,再在绘图控件上把此图形画出来即可看的像动一样。

drawMoving函数的实现如下:

void CTeeChartDlg::drawMoving(){ CSeries chart_T = (CSeries)m_Chart.Series(0) chart_T.Clear() m_pLineSerie->ClearSerie() LeftMoveArray(m_TeeChartArray,m_c_arrayLength,randf(0,10)) LeftMoveArray(m_X,m_c_arrayLength,m_count) DrawLine_TeeChart(m_X,m_TeeChartArray,m_c_arrayLength)}

前面说过timer是优先级最低的消息,如果想曲线动的流畅,可以把时钟设置为0ms,如 SetTimer(0,0,NULL)

这时会在保证界面流畅的前提下,以最高频率刷新。这样看到的图形会非常流畅。

上面介绍的就是动态绘制曲线的思路和方法,附件中有用TeeChart实现和HightSpeedChart实现的例子,考虑到可能有些人没有安装TeeChart,专门把TeeChart分离出来了一个源码,只有HightSpeedChart,不需要安装任何控件。

demo1:

MFC下TeeChart和HightSpeedChart动态绘制曲线图-VS2010

demo2(不用安装任何控件):

MFC动态绘制曲线图-HightSpeedChart实现


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/bake/11682901.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-17
下一篇2023-05-17

发表评论

登录后才能评论

评论列表(0条)

    保存