转:MFC中绘制动态曲线

标签:
mfc绘制动态曲线picture-control |
分类: MFC学习历程 |
在工控监测领域,经常需要动态绘制曲线,观察曲线的变化趋势,绘制波形图,绘制频谱等。在前面4讲中介绍了MFC经常用的TeeChart控件和Hight-Speed
Chart
C++ GUI 绘图控件目录 MFC(VC)
Qt
|
http://img.blog.csdn.net/20140228151349109
http://img.blog.csdn.net/20140228151548078
对于任何绘图控件,都可以实现动态绘图,其原则是:控件只负责绘图,若想曲线动,就让数据动,就像看电影一样,电影是由一帧一帧的静态图片组合起来的,在一定速度上刷新,静态图片就能动起来;和电影的原理一样,绘图控件能显示静态的曲线,想要它动起来,就让它频在一定时间刷新就可以了。 |
这就是动态绘图的实现原理。
实现动态曲线需要以下两个准备:
- 计时器Timer
- 数组左移
基于Timer的绘图
任何界面库都会有Timer这个实现,在MFC中时OnTimer消息,在Qt中是QTimer类,那种原理基本都一样,下面将以MFC(VC)为例进行说明。
Timer是消息级别最低的消息,它会保证其它级别高的消息优先执行,因此,就算数据大量刷新,也不会影响主线程的其它消息。
MFC生成OnTimer消息,消息响应函数如下:
-
void
CTeeChartDlg::OnTimer( UINT_PTRnIDEvent) -
{
-
// TODO: 在此添加消息处理程序代码或调用默认值 -
CDialogEx::OnTimer(nIDEvent); -
}
绘图的实现就在这个消息响应函数里
如果让定时器设定为1秒触发,每一秒把旧数据去除,绘制新数据,就能看到不停变换的波形;对于趋势图,假如每秒有一个新数据,那么就在定长数组中,把数组所有数据整体左移,同时数组末端加入新数据。代码如下:
-
///
-
///
\brief 左移数组 -
///
\param ptr 数组指针 -
///
\param data 新数值 -
///
-
void
LeftMoveArray( double*ptr, size_tlength, doubledata) -
{
-
for ( size_ti=1;i -
{ -
ptr[i-1] = ptr[i]; -
} -
ptr[length-1] = data; -
}
这样,数组就实现“向左运动”,把左移后的数组绘制,就能在绘图控件上发现其变化。
下面开始实现动态绘图(这里演示TeeChart的方法,附件里有HightSpeed-Chart CChartCtrl的方法):
-
void
CTeeChartDlg::OnBnClickeonRuning() -
{
-
KillTimer(0); -
ZeroMemory(&m_TeeChartArray,sizeof(double)*m_c_arrayLength); -
for ( size_ti=0;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_PTRnIDEvent) -
{
-
// 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(不用安装任何控件):