.NET图表控件chart绘制折线图

Author Avatar
小林QAQ 08月 09,2020
  • 在其它设备中阅读本文章

最近有同学在做大创,用到了.NET,花了一个晚上研究图表控件绘制折线图这部分内容,现在简单记录一下思考过程和解决方案。

第一步,看需求,大概需求是在.NET项目中绘制一个折线图,随着传入数据的变化实时更新折线图显示。需要绘制两条折线,分别反映温度和湿度随时间的变化情况。

绘制折线图,这里选用的是.NET的chart控件。首先主要了解一下chart控件的两个集合属性:
ChartAreas:图表区集合,可以设置图表区域相关属性,如网格颜色,坐标轴名称等。
Series:图表序列集合,可以设置图表序列相关属性,如图表类型,坐标值显示类型,标记图案,图案颜色等。
其他属性自行查询文档或使用搜索引擎,这里不再一一介绍。

接下来就是正式编码部分,这里使用的是VS2019,创建的项目是Windows窗体应用(.NET Framework)。
首先我们需要一个chart控件,可以从“工具箱-数据”中直接拖出,也可以使用代码手动创建一个。由于这里折线图在程序启动时即存在,所以我们直接手动拖出一个chart控件对象的实例chart1。设置一下chart1的属性,首先将ChartAreas中的ChartArea1成员的Asis集合中的X和Y成员的Title属性修改为想要的坐标轴名称(有点绕,可以用代码代替,写在WinLoad事件下,如下):

chart1.ChartAreas["ChartArea1"].AxisX.Title = "(你想要的x轴名称)";
chart1.ChartAreas["ChartArea1"].AxisY.Title = "(你想要的y轴名称)";

然后修改Series属性,需要几条折线就添加几个成员,并且设置Name属性为折线的名称,XValueType为横坐标类型,YValueType为纵坐标类型,最重要的是把ChartType属性设置为Line,这样折线图基本设置就完成了。

考虑到我们需要实时更新数据,不能一直往Serise中塞数据,不然生成的折线会超出显示范围。所以这里使用到了.NET的队列类Queue。双击窗体进入Form1.cs的代码设计界面,引入System.Collections命名空间,在Form1类里定义Queue对象:

Queue timex = new Queue();//时间队列
Queue temy = new Queue();//温度队列
Queue humy = new Queue();//湿度队列

并在窗体初始化事件Form1_Load中使用for循环为队列赋初始值0:

for (int i = 0; i < 10 ;i++)
{
    timex.Enqueue("0");
}
for (int i = 0; i < 10; i++)
{
    temy.Enqueue("0");
}
for (int i = 0; i < 10; i++)
{
    humy.Enqueue("0");
}

先讲解一下接下来的思路,由于Series中Points集合只能调用AddXY同时添加点的X值和Y值或添加Y值,无法单独添加X值,并且添加Y值后无法修改X值,所以只能同时给X值和Y值赋值。这里由于两个队列使用foreach循环无法实现,所以将队列暂时复制到新的数组中实现对折线图点的赋值。
先在队列定义处(Form1类中)定义数组:

Object[] stime;
Object[] stem;
Object[] shum;

之后在需要更新数据的地方(这里为invoke方式,也可使用计时器)执行如下操作:

  1. 队列入队一个元素,然后出队一个元素完成数据更新;
  2. 清空Series中所有点;
  3. 将队列元素复制到新的数组中;
  4. 使用for循环给Series中的点赋值。

在这个样例中,代码如下:

timex.Enqueue(DateTime.Now.ToLongTimeString());//获取系统时间入列
timex.Dequeue();//将队列最前的数据出列
temy.Enqueue(label4.Text);//获取温度入列
temy.Dequeue();//将队列最前的数据出列
humy.Enqueue(label7.Text);//获取湿度入列
humy.Dequeue();//将队列最前的数据出列
chart1.Series["温度"].Points.Clear();//清空温度Series中所有点
chart1.Series["湿度"].Points.Clear();//清空湿度Series中所有点

stime = timex.ToArray();//将时间队列复制到数组中
stem = temy.ToArray();//将温度队列复制到数组中
shum = humy.ToArray();//将湿度队列复制到数组中
for (int j = 0; j < 10; j++)
{
    chart1.Series["温度"].Points.AddXY(stime[j], stem[j]);//给温度Series的点赋值
    chart1.Series["湿度"].Points.AddXY(stime[j], shum[j]);//给湿度Series的点赋值
}

最后效果如下:
效果

初始折线图为值为0的一条直线,数据更新时,折线向左移动,右侧出现新点。