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. Java网络编程 -- BIO 阻塞式网络编程

    阻塞IO的含义 阻塞(blocking)IO :阻塞是指结果返回之前,线程会被挂起,函数只有在得到结果之后(或超时)才会返回 非阻塞(non-blocking)IO :非阻塞和阻塞的概念相对应,指在不 ...

  2. 企查查app (二)

    企查查app sign算法破解 已删除!!!! 这次我们又找到设备id,现在就只差aXM这个了. 关注小白公众号,小白带你成长.

  3. java 路径问题

    java路径存在两种写法"/"和"\\" String path="D:\\1.txt"; String path1="D:/1. ...

  4. Python学习 之三 Python基础&运算符

    第三章:Python基础 & 运算符 3.1 内容回顾 & 补充 计算机基础 编码 字符串: "中国" "Hello" 字 符: 中 e 字 节 ...

  5. HOWTO: Amira/Avizo中如何设置数据尺度单位

    很多朋友是数据量化完成后,问统计表中的数据尺度单位,这种情况恐怕需要从头再处理一次,所以对于Amira/Avizo的新用户来说,在准备进行量化分析之前就应该设置好尺度单位,设置步骤如下: 1.  在A ...

  6. 数据结构C线性表现实

    linearList.h #ifndef _INC_STDIO_8787 #define _INC_STDIO_8787 #include <stdio.h> #include <m ...

  7. c# webapi结合swagger的使用

    一.使用nuget下载swagger包 Install-Package Swashbuckle 二.配置swagger 1. 安装完Swashbuckle后,nuget会将相关引用添加至WebApi项 ...

  8. P2762 太空飞行计划问题 最大权闭合子图

    link:https://www.luogu.org/problemnew/show/P2762 题意 承担实验赚钱,但是要花去对应仪器的费用,仪器可能共用.求最大的收益和对应的选择方案. 思路 这道 ...

  9. gym/102021/J GCPC18 模拟拼图

    模拟拼图 题意: 给定n块拼图,每个拼图为四方形,对应四条边有四个数字,如果为0,表示这个边是在边界的,其他数字表示和另一个拼图的一条边相接.保证每个非零数只出现两次. 思路: 模拟,但是要注意几个情 ...

  10. codeforces D. Mahmoud and Ehab and the binary string(二分)

    题目链接:http://codeforces.com/contest/862/submission/30696399 题解:这题一看操作数就知道是二分答案了.然后就是怎么个二分法,有两种思路第一种是找 ...