【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
? ? ? ? 数据采集和监控是上位机开发一项很基础的功能。采集数据的多少,采集的频率,这个取决于具体的项目类型。采集数据之后的处理,一般由于项目的不同,也是不一样的。总之,对于制造业的朋友,特别是生产端的程序员来说,数据采集是他们经常遇到的一个工作任务。
? ? ? ? 目前关于数据的显示和调整,有很多的方式和方法。不过,我还是建议大家可以自己写一个canvas,累积一下相关的知识点,这样在应用的时候才会得心应手。为了实现这样一个demo程序,我们可以用随机数来进行代替。同样为了说明采集频率,我们也可以用定时器来模拟一下。
? ? ? ? 界面的部分其实很简单,主要就是一个canvas。但实际应用的时候,可能还会有一些子对话框、子控件等等。当然,我们学会了canvas之后,就可以把它放在自己的项目当中去。
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SensorDataChart" Height="400" Width="600">
<Grid x:Name="grid">
<Canvas Name="chartCanvas" Background="LightGray" />
</Grid>
</Window>
? ? ? ? 要实现一个动态显示的效果,有几点需要注意一下。第一,需要一个定时器,模拟一下采样频率;第二,需要一个随机数,模拟一下传感器的采集量;第三,就是添加相关的逻辑判断,特别是一次显示多少数据。
? ? ? ? 目前,代码是一次展示100个点的采集。超过100个点之后,第一个点将被扔掉,最后一个点补上。后续的逻辑也是如此。此外,每次显示的时候,都选择清空画布和重新绘制折线图。绘制的方法就比较简单了,相连两点直接连接起来就可以了。
? ? ? ? 因为有定时器的缘故,所以相关数据会不停地生成出来,并显示。这和实际传感器的效果几乎是一样的。有兴趣的同学,可以把这个chart移植到真实的传感器上面,相信会有更加深刻的认识。
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace WpfApp
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private List<Point> dataPoints = new List<Point>();
private DispatcherTimer timer;
private int num = 0;
public MainWindow()
{
InitializeComponent();
// 创建定时器
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(50); // 设置定时器间隔(40ms)
timer.Tick += Timer_Tick;
// 启动定时器
timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
// 生成随机y值,x值为固定值
Random random = new Random();
double randomY = random.Next(140, 200);
if (num < 500)
{
Point randomPoint = new Point(80 + num, randomY);
num += 5;
dataPoints.Add(randomPoint);
}
else
{
List<Point> new_dataPoints = new List<Point>();
for(int i = 1; i < 100; i+=1)
{
Point Point = new Point(dataPoints[i].X-5, dataPoints[i].Y);
new_dataPoints.Add(Point);
}
Point randomPoint = new Point(80 + num - 5, randomY);
new_dataPoints.Add(randomPoint);
dataPoints = new_dataPoints;
}
// 清空画布
chartCanvas.Children.Clear();
// 重新绘制折线图
DrawLineChart(dataPoints);
}
private void DrawLineChart(List<Point> points)
{
if (points == null || points.Count < 2)
return;
// 创建画笔
SolidColorBrush lineColor = Brushes.Blue;
double lineWidth = 2;
Pen linePen = new Pen(lineColor, lineWidth);
// 绘制折线
for (int i = 0; i < points.Count - 1; i++)
{
Line line = new Line
{
X1 = points[i].X,
Y1 = points[i].Y,
X2 = points[i + 1].X,
Y2 = points[i + 1].Y,
Stroke = lineColor,
StrokeThickness = lineWidth
};
chartCanvas.Children.Add(line);
}
}
}
}
? ? ? ? 代码编写完整后,没有问题的话,就可以开始测试。一开始数据还没有满的时候,折线是慢慢添加上去的,
? ? ? ? 等到100个数据全部采集完之后,数据开始流动了,如下所示,
? ? ? ? 如果能够同时看到以上这两个现象,基本就达到我们设计的效果了。