MFC中绘制动态曲线

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


C++ GUI 绘图控件目录

MFC(VC)

Qt


















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

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

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

  1. 计时器Timer
  2. 数组左移

基于Timer的绘图

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

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

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void CTeeChartDlg::OnTimer(UINT_PTR nIDEvent)  
  2. {  
  3.     // TODO: 在此添加消息处理程序代码或调用默认值  
  4.     CDialogEx::OnTimer(nIDEvent);  
  5. }  

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

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. ///   
  2. /// \brief 左移数组  
  3. /// \param ptr 数组指针  
  4. /// \param data 新数值  
  5. ///  
  6. void LeftMoveArray(double* ptr,size_t length,double data)  
  7. {  
  8.     for (size_t i=1;i<length;++i)  
  9.     {  
  10.         ptr[i-1] = ptr[i];  
  11.     }  
  12.     ptr[length-1] = data;  
  13. }  
此函数把整个数组左移,然后新数据放置在数组最末端(右端)。

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

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void CTeeChartDlg::OnBnClickedButtonRuning()  
  2. {  
  3.     KillTimer(0);  
  4.     ZeroMemory(&m_TeeChartArray,sizeof(double)*m_c_arrayLength);  
  5.     for (size_t i=0;i<m_c_arrayLength;++i)  
  6.     {  
  7.         m_X[i] = i;  
  8.     }  
  9.     m_count = m_c_arrayLength;  
  10.     CSeries chart_T = (CSeries)m_Chart.Series(0);  
  11.     chart_T.Clear();  
  12.     m_pLineSerie->ClearSerie();  
  13.     SetTimer(0,1000,NULL);    
  14. }  
函数中几个成员变量的定义是:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. double m_TeeChartArray[2096];  
  2. double m_X[2096];  
  3. unsigned int m_count;  
  4. const size_t m_c_arrayLength = 2096;  

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

在timer中的实现如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void CTeeChartDlg::OnTimer(UINT_PTR nIDEvent)  
  2. {  
  3.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  4.     if(0 == nIDEvent)  
  5.     {  
  6.         ++m_count;  
  7.         drawMoving();  
  8.     }  
  9.     CDialogEx::OnTimer(nIDEvent);  
  10. }  

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

drawMoving函数的实现如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void CTeeChartDlg::drawMoving()  
  2. {  
  3.     CSeries chart_T = (CSeries)m_Chart.Series(0);  
  4.     chart_T.Clear();  
  5.     m_pLineSerie->ClearSerie();  
  6.     LeftMoveArray(m_TeeChartArray,m_c_arrayLength,randf(0,10));  
  7.     LeftMoveArray(m_X,m_c_arrayLength,m_count);  
  8.     DrawLine_TeeChart(m_X,m_TeeChartArray,m_c_arrayLength);  
  9. }  

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. SetTimer(0,0,NULL);   
这时会在保证界面流畅的前提下,以最高频率刷新。这样看到的图形会非常流畅。

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


demo1:

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

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

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


  • 11
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
MFC(Microsoft Foundation Class)是微软开发的一个应用程序框架,它简化了Windows图形用户界面(GUI)应用程序的开发。要使用MFC绘制动态曲线,我们可以通过调用MFC提供的绘图函数来实现。 首先,我们需要在MFC应用程序的视图类的OnDraw函数进行绘图。在该函数,我们可以使用一系列绘图函数来绘制静态曲线,例如MoveTo和LineTo函数。然而,要实现动态曲线绘制,我们需要将这些绘图函数与计时器或消息处理函数结合起来。 一种常见的方法是使用计时器,在每次计时器触发时,更新曲线绘制位置。我们可以定义一个计时器,并在计时器消息函数更新曲线的坐标。在OnDraw函数,我们使用这些更新后的坐标来绘制曲线。这样就可以实现动态曲线绘制了。 另一种方法是使用消息处理函数来实现动态曲线绘制。我们可以在窗口类重载PreTranslateMessage函数,捕获鼠标或键盘消息,并在其处理过程更新曲线的坐标。然后在OnDraw函数使用这些更新后的坐标来绘制曲线。 无论使用哪种方法,我们都需要定义曲线的坐标,例如一个数组来存储X轴和Y轴的坐标点。然后在OnDraw函数使用这些坐标来绘制曲线。通过不断更新这些坐标,曲线就可以实现动态效果。 当然,以上只是一个实现动态曲线绘制的思路,具体的源码实现可能因个人需求而有所不同。但是无论怎样,考虑到MFC的特点和功能,我们可以利用MFC提供的绘图函数和消息处理机制来方便地实现动态曲线绘制

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值