Prepare
本文将使用一个NuGet公开的组件来实现曲线的显示,包含了多种显示的模式和配置来满足各种不同的应用场景,方便大家进行快速的开发系统。
在Visual Studio 中的NuGet管理器中可以下载安装,也可以直接在NuGet控制台输入下面的指令安装:
Install-Package HslCommunication
NuGet安装教程 http://www.cnblogs.com/dathlin/p/7705014.html
技术支持QQ群:592132877 (组件的版本更新细节也将第一时间在群里发布)
如果你在使用控件的过程中有什么疑问,或是发现了BUG,或是功能建议,等等都可以加入上面的QQ群进行讨论。文章更新时间:2018年1月24日 18:25:50
接下来的计划支持:
- 计划支持X轴文本信息显示,但是具体的逻辑实现还是有待确认,如何更好的显示
- 计划支持鼠标在数据上挪动时动态显示数据值
Summary
曲线控件属于组件里诸多控件中的一种,为什么单独拿出来写一篇博客呢,就是因为曲线控件相对于其他控件都要复杂很多,并不是几个属性那么简单,下面列举了本曲线控件的特性:
- 提供便捷的API调用即可显示曲线信息内容,不需要复杂的配置
- 曲线界面的一些信息可以自由定制,比如坐标轴的颜色,是否显示虚线等等
- 高度的大小自适应,无论你怎么调整控件的大小,始终都能友好显示
- 支持数据拉伸填充和像素点填充两种模式,具体区别参照下面的代码
- 多曲线支持,支持同时显示多个曲线信息,每个曲线可独立的指定颜色,线宽等等。
- 支持左右两个参考系,就是说一个控件中允许显示2种数据跨度不一致的曲线,每种曲线可以显示多条不同的曲线
其他控件的说明地址:http://www.cnblogs.com/dathlin/p/8150516.html
组件的完整API说明:http://www.cnblogs.com/dathlin/p/7703805.html
要想使用组件的控件,除了使用NuGet来安装组件外,还需要将组件的dll文件(在你的项目的packages里面可以找到,如果你本来就是引用本地的,就直接拖拽本地的即可)拖拽到工具栏:
拖拽完成后效果如下:
1.单曲线使用
把控件拖拽到窗口界面上去后,现在界面如下,你可以随意的拉伸大小,调整到一个虚线看着比较清晰的时刻停止:
我们看到左右纵轴的数据跨度都是0-100,现在我们有个需求,手里有300个0-200的数据需要显示,那么就要先设置左右纵轴的数据跨度
接下来就可以编写显示的代码了,一下数据随机:
private void userButton1_Click( object sender, EventArgs e ) { float[] data = new float[300]; for (int i = 0; i < data.Length; i++) { data[i] = random.Next( 201 ); } userCurve1.SetLeftCurve( "A", data, Color.DodgerBlue ); }
显示结果如下:
看吧,相当简单方便,如果你觉得目前的数据太密了,想要宽松一点,希望数据拉伸满整个X轴,没问题,因为目前默认的模式是像素点模式,所以切换为拉伸模式即可。
然后在运行看看效果:
接下来我们要对曲线“A”进行数据更新,我们假设你的data数组的数据已经更新了,有可能只更新了一个数据,有可能全部更新了,在数据更新的时候就需要在指定颜色了,因为指定了颜色也没有用了。
private void userButton3_Click( object sender, EventArgs e ) { // 假设你的data数组已经更新了 float[] data = new float[300]; for (int i = 0; i < data.Length; i++) { data[i] = random.Next( 100, 201 ); } // 之前已经给A指定过颜色了,以后后续的数据更新不需要重新指定,指定了也无效 // 如果需要重新设置颜色,或是线宽,需要先RemoveCurve,然后重新创建曲线信息 userCurve1.SetLeftCurve( "A", data ); }
从上面的数据更新我们发现,只要更新了数据,就不停的调用数据显示,那么我们就可以显示实时数据了,而唯一的麻烦之处在于我们需要维护自己的data数组。所以当前的这种方式只适合静态数据显示
2.单曲线实时数据
当我们需要显示一些实时数据时,也就是说,每隔1秒(随便举个栗子)就有新的数据采集上来,然后追加到曲线中去,曲线进行挪动,通常就是这种情况。
2.1 像素点模式(请确认 IsAbscissaStrech 为False):
我们先讲解默认的模式,所谓像素点模式是指在横轴上,一个像素点显示一个数据,如果你的横轴像素长度为1000,那么你就可以显示1000个数据了,当然在实时显示的情况下,不需要你管那么多,你只需要负责定期往里面塞数据即可。
第一步先进行初始化:先增加指定名字的曲线信息,曲线颜色,曲线宽度等等
private void userButton4_Click( object sender, EventArgs e ) { // 这里传入了数组长度为空的数据,不能传NULL userCurve1.SetLeftCurve( "B", new float[] { }, Color.Tomato ); }
我们再写一个按钮,启动定时器,去新增数据,来模拟我们从其他设备读取到的数据信息:
private void userButton5_Click( object sender, EventArgs e ) { Timer timer = new Timer( ); timer.Interval = 100; timer.Tick += ( sender1, e1 ) => { userCurve1.AddCurveData( "B", random.Next( 50, 201 ) ); }; timer.Start( ); }
如上面的两个按钮信息,必须先点击按钮4进行曲线初始化,按钮5的点击才有效果。最终你会看到曲线每隔100ms刷新一次,不停的有新的数据递增。
当曲线数量超过当前可显示的点数时,曲线会自动的往左挪动,即时你拉伸的整个控件,它依然可以正常的工作,可显示的数据点数会自动更新,内存中会缓存2048个数据点来支持拉伸的效果转换。
当然,它也支持一次更新多个数据,虽然这种情况很少,只是需要注意的是,一次更新的数据必须少于2048。
userCurve1.AddCurveData( "B", new float[] { random.Next( 50, 201 ), random.Next( 50, 201 ), random.Next( 50, 201 ) } );
2.2 拉伸模式(请确认 IsAbscissaStrech 为True):
拉伸模式的意思是无论你的data数组有多少个点,都强行拉伸完整个横轴界面,即时只有2个数据,或者是1000个数据,我们可以先看看这个初步的效果
private void userButton4_Click( object sender, EventArgs e ) { // 这里传入了数组长度为空的数据,不能传NULL userCurve1.SetLeftCurve( "B", new float[] { }, Color.Tomato ); } private void userButton5_Click( object sender, EventArgs e ) { Timer timer = new Timer( ); timer.Interval = 100; timer.Tick += ( sender1, e1 ) => { userCurve1.AddCurveData( "B", random.Next( 50, 201 ) ); }; timer.Start( ); }
可以看到,除了修改下属性,就可以测试了,我随便截取个界面:
可以看到所有的曲线信息往左开始一步步挪动。但是还是有个问题,这样一直往左挪动。那么这个曲线就会越来越密。那怎么办,总有个上限吧,那么代码修改成下面的:
private void userButton4_Click( object sender, EventArgs e ) { // 这里传入了数组长度为空的数据,不能传NULL userCurve1.SetLeftCurve( "B", new float[] { }, Color.Tomato ,500); // 指定上限500个数据,该上限只对拉伸模式有效 } private void userButton5_Click( object sender, EventArgs e ) { Timer timer = new Timer( ); timer.Interval = 100; timer.Tick += ( sender1, e1 ) => { userCurve1.AddCurveData( "B", random.Next( 50, 201 ) ); }; timer.Start( ); }
我们再看拉伸模式的曲线:
你再拉伸控件试试看?拉伸模式的意思是无论你的控件多少大小,你规定了500个点,它就是500个点,即使你的控件拉伸了,它还是500个点,只是没有那么密罢了
至于一次增加多个数据是和上面的像素点模式是一致的。
2.3 模式区别及选择
像素点模式下,随便看着数据比较密,但是好处在于分辨率高的显示器,可以显示的数据更多。
拉伸模式虽然在控件拉伸的情况下显示的数据量不会增长,但是可以控制疏密程度。
各有优劣,建议先使用像素点模式,看看效果怎么样,一般数据变化都是慢慢来的,所以曲线不会像测试数据那样乱串。如果数据乱串比较厉害,再使用拉伸模式。
3.多曲线使用
多曲线和单曲线模式很相似,无非是多几条曲线而已,每条曲线的操作,新增数据都是一模一样的,只是多曲线的模式都是统一的,要么全部是像素点模式,要么全部是拉伸模式,所有的特性和上两节是相似的。
为了说明使用,举个例子,你有多个设备(2个及以上),每个设备都有一个温度信息,现在要进行实时数据的直接对比,当然最好将三条曲线放到一起显示。
我们命名三个曲线为“A”,“B”,“C” 然后假设所有的数据都是100-200之间,数据A是160-180随机,数据B是150-170随机,数据C是155-165随机
此处测试方便,使用了 像素点模式。在 拉伸模式 下代码也是一致的
初始化按钮及启动定时器按钮代码如下:
private void userButton4_Click( object sender, EventArgs e ) { userCurve1.SetLeftCurve( "A", new float[] { }, Color.Tomato ); userCurve1.SetLeftCurve( "B", new float[] { }, Color.DodgerBlue ); userCurve1.SetLeftCurve( "C", new float[] { }, Color.LimeGreen ); } private void userButton5_Click( object sender, EventArgs e ) { Timer timer = new Timer( ); timer.Interval = 100; timer.Tick += ( sender1, e1 ) => { userCurve1.AddCurveData( new string[] { "A", "B", "C" }, new float[] { random.Next( 160, 181 ), random.Next( 150, 171 ), random.Next( 155, 165 ) } ); }; timer.Start( ); }
在新增数据的代码上,此处使用了一条指令来新增三条数据,当然你也可以通过写三条指令,分别新增,注意,那样会导致界面刷新三次!所以不建议。
界面如下:
3.双坐标使用
我们接下来看一种相当复杂的使用场景,假设我们有一台设备,需要监控4条曲线,2条温度,2条压力,温度的范围是0-200,压力的范围为0-5 mpa,那么想要在一个控件里显示,也是可以实现的。先调整左右的坐标范围。
此处仍然使用像素点模式,我们接下来写初始化代码和新增数据的代码:
private void userButton4_Click( object sender, EventArgs e ) { userCurve1.SetLeftCurve( "A", new float[] { }, Color.Tomato ); // 温度1 userCurve1.SetLeftCurve( "B", new float[] { }, Color.DodgerBlue ); // 温度2 userCurve1.SetLeftCurve( "C", new float[] { }, Color.LimeGreen ); // 压力1 userCurve1.SetLeftCurve( "D", new float[] { }, Color.Purple ); // 压力2 } private void userButton5_Click( object sender, EventArgs e ) { Timer timer = new Timer( ); timer.Interval = 100; timer.Tick += ( sender1, e1 ) => { userCurve1.AddCurveData( new string[] { "A", "B", "C", "D" }, new float[] { random.Next( 160, 181 ), random.Next( 150, 171 ), (float)random.NextDouble( ) * 3.5f, (float)random.NextDouble( ) * 1f } ); }; timer.Start( ); }
效果如下图:
4.背景颜色调整
我修改下背景为暗黑色,瞬间就有黑科技的效果了。当然,线条的颜色可以调整的更加好一点
4.结束语
感谢阅读。