C#中可选的绘图工具有很多,除了Oxyplot还有DynamicDataDisplay(已经改名为InteractiveDataDisplay)等等。不过由于笔者这里存在一些环境上的特殊要求,.Net Framework的版本被限制在4,而InteractiveDataPlay要求的最低版本是4.5.2。所以选择了对版本要求较低的Oxyplot。

IDE为VS2012,创建工程后首先通过NuGet程序包管理器控制台,通过下述命令添加对Oxyplot的引用:

PM> Install-Package Oxyplot.Core
PM> Install-Package Oxyplot.Wpf

XAML里添加上必要的引用:

<Window x:Class="MonitorForm.MonitorForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MonitorForm"
xmlns:oxy="http://oxyplot.org/wpf"
Title="MainWindow" Height="350" Width="525">
<Grid>
<oxy:PlotView Model="{Binding Path= SimplePlotModel}"></oxy:PlotView> </Grid>
</Window>

笔者的开发场景是需要统计四类数据,因此开放四个公共方法供外部调用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Threading; namespace MonitorForm { /// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MonitorForm : Window { private PlotViewModel _viewModel; public MonitorForm() { InitializeComponent(); _viewModel = new PlotViewModel();
this.DataContext = _viewModel;
} public void addSendCount(int iCount) { _viewModel.addSendCount(iCount);
} public void addUnsendCount(int iCount) { _viewModel.addUnsendCount(iCount);
} public void addConfirmCount(int iCount) { _viewModel.addConfirmCount(iCount);
} public void addDealCount(int iCount) { _viewModel.addDealCount(iCount);
}
}
}

MVVM模式,需要添加ViewModel层:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OxyPlot;
using OxyPlot.Series;
using OxyPlot.Axes;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Concurrent; namespace MonitorForm { public class PlotViewModel { /// <summary>
/// 画直线
/// </summary>
public PlotModel SimplePlotModel { get; set; } //每条线对应一个队列用作实时数据统计
private ConcurrentQueue<int> queueSend = new ConcurrentQueue<int>();
private ConcurrentQueue<int> queueUnsend = new ConcurrentQueue<int>();
private ConcurrentQueue<int> queueConfirm = new ConcurrentQueue<int>();
private ConcurrentQueue<int> queueDeal = new ConcurrentQueue<int>(); public void addSendCount(int iCount) { queueSend.Enqueue(iCount);
} public void addUnsendCount(int iCount) { queueUnsend.Enqueue(iCount);
} public void addConfirmCount(int iCount) { queueConfirm.Enqueue(iCount);
} public void addDealCount(int iCount) { queueDeal.Enqueue(iCount);
} public int getSendCount() { int iSingle = ;
int iTotal = ;
while (queueSend.TryDequeue(out iSingle)) { iTotal += iSingle;
} return iTotal;
} public int getUnsendCount() { int iSingle = ;
int iTotal = ;
while (queueUnsend.TryDequeue(out iSingle)) { iTotal += iSingle;
} return iTotal;
} public int getConfirmCount() { int iSingle = ;
int iTotal = ;
while (queueConfirm.TryDequeue(out iSingle)) { iTotal += iSingle;
} return iTotal;
} public int getDealCount() { int iSingle = ;
int iTotal = ;
while (queueDeal.TryDequeue(out iSingle)) { iTotal += iSingle;
} return iTotal;
} public PlotViewModel() { SimplePlotModel = new PlotModel(); //创建于建立初始化数据节点
var lineSend = new LineSeries() { Title = "报送" };
lineSend.Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), ));
SimplePlotModel.Series.Add(lineSend); var lineUnsend = new LineSeries() { Title = "待报送" };
lineUnsend.Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), ));
SimplePlotModel.Series.Add(lineUnsend); var lineConfirm = new LineSeries() { Title = "确认" };
lineConfirm.Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), ));
SimplePlotModel.Series.Add(lineConfirm); var lineDeal = new LineSeries() { Title = "成交" };
lineDeal.Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), ));
SimplePlotModel.Series.Add(lineDeal); //定义y轴
LinearAxis leftAxis = new LinearAxis() { Position = AxisPosition.Left,
Minimum = ,
Maximum = ,
Title = "笔数",//显示标题内容
TitlePosition = ,//显示标题位置
MajorGridlineStyle = LineStyle.Solid,
MinorGridlineStyle = LineStyle.None,
}; //定义x轴 报盘监控界面x轴统一为时间
DateTimeAxis bottomAxis = new DateTimeAxis() { Position = AxisPosition.Bottom,
StringFormat = "hh:mm:ss",
Minimum = DateTimeAxis.ToDouble(DateTime.Now),
Maximum = DateTimeAxis.ToDouble(DateTime.Now.AddMinutes()),
Title = "时间",
TitlePosition = ,
IntervalLength = ,
MinorIntervalType = DateTimeIntervalType.Seconds,
IntervalType = DateTimeIntervalType.Seconds,
MajorGridlineStyle = LineStyle.Solid,
MinorGridlineStyle = LineStyle.None,
}; SimplePlotModel.Axes.Add(leftAxis);
SimplePlotModel.Axes.Add(bottomAxis); bool bToMove = false;
Task.Factory.StartNew(() => { while (true) { lineSend.Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), getSendCount()));
lineUnsend.Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), getUnsendCount()));
lineConfirm.Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), getConfirmCount()));
lineDeal.Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), getDealCount())); if (!bToMove) { //当前时间减去起始时间达到30秒后开始左移时间轴
TimeSpan timeSpan = DateTime.Now - DateTimeAxis.ToDateTime(bottomAxis.Minimum);
if (timeSpan.TotalSeconds >= ) { bToMove = true;
}
} else { //左移时间轴,跨度维持在60秒
bottomAxis.Minimum = DateTimeAxis.ToDouble(DateTime.Now.AddSeconds(-));
bottomAxis.Maximum = DateTimeAxis.ToDouble(DateTime.Now.AddSeconds()); //删除历史节点,防止DataPoint过多影响效率,也防止出现内存泄漏
lineSend.Points.RemoveAt();
lineConfirm.Points.RemoveAt();
lineUnsend.Points.RemoveAt();
lineDeal.Points.RemoveAt();
} //根据报单笔数判断是否需要更新y轴刻度 //首先找出四条统计线中当前最大的节点
double iMax = lineSend.MaxY;
if (iMax < lineConfirm.MaxY) {
iMax = lineConfirm.MaxY;
}
if (iMax < lineUnsend.MaxY) {
iMax = lineUnsend.MaxY;
}
if (iMax < lineDeal.MaxY) {
iMax = lineDeal.MaxY;
} //如果当前的y轴最大刻度小于数据集中的最大值,放大
leftAxis.Maximum = iMax + ( - iMax % );
leftAxis.IntervalLength = leftAxis.Maximum / ; //每秒刷新一次视图
SimplePlotModel.InvalidatePlot(true);
Thread.Sleep();
}
});
}
}
}

从上述代码可以看出,功能主要为实现了Y轴为笔数统计,而X轴为时间轴且当线画到了中间时开始左移时间轴。统计的间隔为1秒。

如果要导出DLL封装给其他程序使用的话,在项目属性中将输出类型调整为类库即可。这时可能会有例如不存在InitializeComponent()之类的报错,将App.xmal属性中的生成操作修改成无即可顺利导出。

自己写了个小DEMO调用该DLL,不停往里添加数据,效果图如下:

时间轴会左移,而Y轴的笔数统计也会根据当前DataPoint集合中的最大值进行相应的调整。

C#使用Oxyplot绘制监控界面的更多相关文章

  1. 【Java框架型项目从入门到装逼】第八节 - 用EasyUI绘制主界面

    1.引入资源包 在上一节中,我们把基本的框架都搭好了,用了Spring,SPringMVC.这一节,我们先来画页面,前端框架采用EasyUI来实现. easyui是一种基于jQuery的用户界面插件集 ...

  2. SpringBoot2.0 基础案例(07):集成Druid连接池,配置监控界面

    一.Druid连接池 1.druid简介 Druid连接池是阿里巴巴开源的数据库连接池项目.Druid连接池为监控而生,内置强大的监控功能,监控特性不影响性能.功能强大,能防SQL注入,内置Login ...

  3. 六:SpringBoot-集成Druid连接池,配置监控界面

    SpringBoot-集成Druid连接池,配置监控界面 1.Druid连接池 1.1 Druid特点 2.SpringBoot整合Druid 2.1 引入核心依赖 2.2 数据源配置文件 2.3 核 ...

  4. kafka-eagle监控界面搭建

    kafka-eagle监控界面搭建 一.背景 二 .mac上安装kafka-eagle 1.安装JDK 2.安装eagle 1.下载eagle 2.解压并配置环境变量 3.启用kafka的JMX 4. ...

  5. AspNet Core下利用 app-metrics+Grafana + InfluxDB实现高大上的性能监控界面

    在日常系统工作中,我们为了洞察系统的问题和运作情况通常会记录日志的方式来进行分析,但是在很多情况下都是被动的在出问题后才会去查日志.在很多时候,我们可能更需要相对实时的了解整个系统或者某一时段的运行的 ...

  6. zabbix结合grafana打造炫酷监控界面

    一.grafana介绍 grafana是一个开源的数据展示工具, 是一个开箱即用的可视化工具,具有功能齐全的度量仪表盘和图形编辑器,有灵活丰富的图形化选项,可以混合多种风格,支持多个数据源特点. za ...

  7. MFC 监控界面上所有文本框值的变化

    //控件消息,菜单,按钮等 BOOL CXXDlg::OnCommand(WPARAM wParam, LPARAM lParam) { // TODO: 在此添加专用代码和/或调用基类 int wm ...

  8. druid 配置监控界面和开启spring支持

    1.配置监控页面 <!-- JNDI方式配置数据源 --> <!-- <bean id="dataSource" class="org.sprin ...

  9. 利用微信小程序实现web监控界面

    1.实现思路 利用小程序去调用公司zabbix的接口获取网站监控数据并展示出来. 2.准备阶段 1.小程序公众号 2.企业号 3.zabbix接口 3.实现过程

随机推荐

  1. 随笔编号-10 window环境下,命令行导入sql脚本详解

    目标:使用window命令行(DOS)导入sql脚本(适用于数据量很大的脚本). 执行步骤: 1  找到mysql bin 文件所在之目录: 2  打开dos命令行界面,win+r 组合键打开运行对话 ...

  2. python 04 列表

    1.列表——list [ ] 有序.可变.支持索引查看. 存储数据,支持大多数数据类型:字符串,数字,布尔值.列表.集合.元组.字典等. 1.1 定义: lst(勿用list)  lst = [&qu ...

  3. Django之静态文件,中间件,admin后台管理

    静态文件 静态文件的使用 在 网页使用的css文件,js文件和图片等叫做静态文件.1)在项目下新建静态文件夹 static. 2) 配置静态文件所在的物理目录.Settings.py STATIC_U ...

  4. 理解Js的parseInt(转)

    parseInt() 方法首先查看位置 0 处的字符,判断它是否是个有效数字:如果不是,该方法将返回 NaN,不再继续执行其他操作.但如果该字符是有效数字,该方法将查看位置 1 处的字符,进行同样的测 ...

  5. IT项目管理入门知识

  6. CodeForces 293E Close Vertices 点分治

    题目传送门 题意:现在有一棵树,每条边的长度都为1,然后有一个权值,求存在多少个(u,v)点对,他们的路劲长度 <= l, 总权重 <= w. 题解: 1.找到树的重心. 2.求出每个点到 ...

  7. poj 3177 Redundant Paths(tarjan边双连通)

    题目链接:http://poj.org/problem?id=3177 题意:求最少加几条边使得没对点都有至少两条路互通. 题解:边双连通顾名思义,可以先求一下连通块显然连通块里的点都是双连通的,然后 ...

  8. codeforces 749D Leaving Auction(二分)

    题目链接:http://codeforces.com/problemset/problem/749/D 题意:就是类似竞拍,然后报价肯定要比上一个高,然后查询输入k个数表示那些人的竞拍无效, 输出最后 ...

  9. 计蒜客 ACM训练联盟周赛 第一场 从零开始的神棍之路 暴力dfs

    题目描述 ggwdwsbs最近被Zeratul和Kyurem拉入了日本麻将的坑.现在,ggwdwsbs有13张牌,Kyurem又打了一张,加起来有14张牌.ggwdwsbs想拜托你帮他判断一下,这14 ...

  10. Zabbix面试总结

    zabbix官方的一句话描述zabbix: 监视任何事情适用于任何IT基础架构,服务,应用程序和资源的解决方案 Monitor anythingSolutions for any kind of IT ...