在WinForm中使用ZedGraph实现多Y轴曲线展示
作者:互联网
在WinForm中使用ZedGraph实现多Y轴曲线展示
背景
在很多业务场景中都会用到基于一个时间轴(X轴)的多个曲线(温度、压力、能量、功率、电流)同时显示的需求。但是这些曲线的Y值范围却相差很大,这样在一个坐标系中展示,会导致某些Y值范围很小的曲线显示趋于一条直线,不容易对曲线进行分析。这样就需要有多个Y轴以支持不同曲线的对应。
实现思路
目前在Winform程序开发中比较常用的图表控件就是TeeChart和ZedGraph,但是TeeChart默认只支持2个Y轴,如果想扩展更多的Y轴,可以使用ZedGraph进行实现。
效果图
先上一张效果图
主要功能
1、实现多Y轴曲线显示;
2、实现X轴以时间文本显示;
3、实现曲线平移(左移和右移);
4、实现曲线的显示与隐藏;
5、实现鼠标点击获取鼠标所在曲线的X轴坐标和Y轴坐标值。
关键代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ZedGraph;
namespace WinZedGraphTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
int fontSize = 9; //字号
int count = 4; //曲线数量
int points = 120; //每条曲线的点数
int maxShowPints = 30; //最大显示的点数
//this.zedGraphControl1.PointValueEvent += zedGraphControl1_PointValueEvent;
//this.zedGraphControl1.MouseMoveEvent += zedGraphControl1_MouseMoveEvent;
this.zedGraphControl1.MouseDownEvent += zedGraphControl1_MouseDownEvent;
this.zedGraphControl1.GraphPane.Title.Text = "多Y轴曲线测试";
this.zedGraphControl1.IsShowPointValues = true;
this.zedGraphControl1.GraphPane.YAxis.MinorGrid.IsVisible = true; //显示横线
this.zedGraphControl1.GraphPane.XAxis.Type = ZedGraph.AxisType.Text; //x轴的类型为文本
this.zedGraphControl1.GraphPane.XAxis.Title.Text = "时间"; //x轴标题
this.zedGraphControl1.GraphPane.XAxis.Title.FontSpec.Size = fontSize;
this.zedGraphControl1.GraphPane.XAxis.Scale.FontSpec.Size = fontSize;
this.zedGraphControl1.GraphPane.YAxis.Title.FontSpec.Size = fontSize;
this.zedGraphControl1.GraphPane.YAxis.Scale.FontSpec.Size = fontSize;
this.zedGraphControl1.GraphPane.Legend.FontSpec.Size = fontSize - 2;
string[] curveTitles = { "曲线1", "曲线2", "曲线3", "曲线4" }; //曲线标题
Color[] colors = { Color.Red, Color.HotPink, Color.Blue, Color.Green }; //颜色
ZedGraph.SymbolType[] symbolTypes = { ZedGraph.SymbolType.None, ZedGraph.SymbolType.Square, ZedGraph.SymbolType.Circle, ZedGraph.SymbolType.Plus }; //符号类型
double[][] xvalues = new double[count][];
string[][] dvalues = new string[count][];
double[][] yvalues = new double[count][];
double[][] ddValues = new double[count][];
Random r = new Random();
r.NextDouble();
ZedGraph.YAxis yAxis = null;
for (int k = 0; k < count; k++)
{
xvalues[k] = new double[points];
dvalues[k] = new string[points];
yvalues[k] = new double[points];
ddValues[k] = new double[points];
for (int i = 0; i < points; i++)
{
xvalues[k][i] = i + 1;
dvalues[k][i] = DateTime.Now.AddSeconds(i).ToString("mm:ss");
ddValues[k][i] = i;
yvalues[k][i] = 20 + (k * 100) + 80 * r.NextDouble();
}
if (k > 0)
{
yAxis = new YAxis();
this.zedGraphControl1.GraphPane.YAxisList.Add(yAxis);
}
LineItem line = this.zedGraphControl1.GraphPane.AddCurve("曲线" + k, ddValues[k], yvalues[k], colors[k], symbolTypes[k]);
line.YAxisIndex = k;
}
this.zedGraphControl1.GraphPane.XAxis.Scale.TextLabels = dvalues[0];
this.zedGraphControl1.GraphPane.XAxis.Scale.Max = maxShowPints;
for (int k = 0; k < this.zedGraphControl1.GraphPane.YAxisList.Count; k++)
{
YAxis y_Axis = this.zedGraphControl1.GraphPane.YAxisList[k];
y_Axis.Title.Text = curveTitles[k];
y_Axis.Color = colors[k];
y_Axis.Scale.FontSpec.FontColor = colors[k];
y_Axis.Title.FontSpec.FontColor = colors[k];
y_Axis.Scale.FontSpec.Size = fontSize;
y_Axis.Title.FontSpec.Size = fontSize;
}
this.zedGraphControl1.AxisChange();
this.zedGraphControl1.Invalidate();
//this.CreateChart(this.zedGraphControl1);
}
/// <summary>
/// 获取鼠标移动的坐标点
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <returns></returns>
private bool zedGraphControl1_MouseMoveEvent(ZedGraphControl sender, MouseEventArgs e)
{
// Save the mouse location
PointF mousePt = new PointF(e.X, e.Y);
string tooltip = string.Empty;
// Find the Chart rect that contains the current mouse location
GraphPane pane = sender.MasterPane.FindChartRect(mousePt);
// If pane is non-null, we have a valid location. Otherwise, the mouse is not
// within any chart rect.
if (pane != null)
{
double x, y;
// Convert the mouse location to X, and Y scale values
pane.ReverseTransform(mousePt, out x, out y);
// 获取横纵坐标信息
tooltip = "(" + x.ToString("f2") + ", " + y.ToString("f2") + ")";
}
Console.WriteLine(tooltip);
return false;
}
/// <summary>
/// 获取鼠标点击的坐标点
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <returns></returns>
private bool zedGraphControl1_MouseDownEvent(ZedGraphControl sender, MouseEventArgs e)
{
// Save the mouse location
PointF mousePt = new PointF(e.X, e.Y);
string tooltip = string.Empty;
// Find the Chart rect that contains the current mouse location
GraphPane pane = sender.MasterPane.FindChartRect(mousePt);
// If pane is non-null, we have a valid location. Otherwise, the mouse is not
// within any chart rect.
if (pane != null)
{
double x, y;
// Convert the mouse location to X, and Y scale values
pane.ReverseTransform(mousePt, out x, out y);
// 获取横纵坐标信息
tooltip = "(X = " + x.ToString("f2") + ", Y = " + y.ToString("f2") + ")";
}
Console.WriteLine(tooltip);
return false;
}
/// <summary>
/// 获取鼠标的坐标点
/// </summary>
/// <param name="sender"></param>
/// <param name="pane"></param>
/// <param name="curve"></param>
/// <param name="iPt"></param>
/// <returns></returns>
private string zedGraphControl1_PointValueEvent(ZedGraphControl sender, GraphPane pane, CurveItem curve, int iPt)
{
string result = "X = " + curve[iPt].X + ", Y = " + curve[iPt].Y;
Console.WriteLine(result);
return result;
}
/// <summary>
/// 曲线左移
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
this.zedGraphControl1.GraphPane.XAxis.Scale.Min--;
this.zedGraphControl1.GraphPane.XAxis.Scale.Max--;
this.zedGraphControl1.Invalidate();
this.zedGraphControl1.Refresh();
}
/// <summary>
/// 曲线右移
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
this.zedGraphControl1.GraphPane.XAxis.Scale.Min++;
this.zedGraphControl1.GraphPane.XAxis.Scale.Max++;
this.zedGraphControl1.Invalidate();
this.zedGraphControl1.Refresh();
}
private void button3_Click(object sender, EventArgs e)
{
if (this.zedGraphControl1.GraphPane.CurveList.Count > 0)
{
this.zedGraphControl1.GraphPane.CurveList[0].IsVisible = !this.zedGraphControl1.GraphPane.CurveList[0].IsVisible;
this.zedGraphControl1.Invalidate();
this.zedGraphControl1.Refresh();
}
}
private void button4_Click(object sender, EventArgs e)
{
if (this.zedGraphControl1.GraphPane.CurveList.Count > 1)
{
this.zedGraphControl1.GraphPane.CurveList[1].IsVisible = !this.zedGraphControl1.GraphPane.CurveList[1].IsVisible;
this.zedGraphControl1.Invalidate();
this.zedGraphControl1.Refresh();
}
}
private void button5_Click(object sender, EventArgs e)
{
if (this.zedGraphControl1.GraphPane.CurveList.Count > 2)
{
this.zedGraphControl1.GraphPane.CurveList[2].IsVisible = !this.zedGraphControl1.GraphPane.CurveList[2].IsVisible;
this.zedGraphControl1.Invalidate();
this.zedGraphControl1.Refresh();
}
}
private void button6_Click(object sender, EventArgs e)
{
if (this.zedGraphControl1.GraphPane.CurveList.Count > 3)
{
this.zedGraphControl1.GraphPane.CurveList[3].IsVisible = !this.zedGraphControl1.GraphPane.CurveList[3].IsVisible;
this.zedGraphControl1.Invalidate();
this.zedGraphControl1.Refresh();
}
}
public void CreateChart(ZedGraphControl zgc)
{
GraphPane myPane = zgc.GraphPane;
// Set the titles and axis labels
myPane.Title.Text = "Demonstration of Multi Y Graph";
myPane.XAxis.Title.Text = "Time, s";
myPane.YAxis.Title.Text = "Velocity, m/s";
myPane.Y2Axis.Title.Text = "Acceleration, m/s2";
// Make up some data points based on the Sine function
PointPairList vList = new PointPairList();
PointPairList aList = new PointPairList();
PointPairList dList = new PointPairList();
PointPairList eList = new PointPairList();
// Fabricate some data values
for (int i = 0; i < 30; i++)
{
double time = (double)i;
double acceleration = 2.0;
double velocity = acceleration * time;
double distance = acceleration * time * time / 2.0;
double energy = 100.0 * velocity * velocity / 2.0;
aList.Add(time, acceleration);
vList.Add(time, velocity);
eList.Add(time, energy);
dList.Add(time, distance);
}
// Generate a red curve with diamond symbols, and "Velocity" in the legend
LineItem myCurve = myPane.AddCurve("Velocity",
vList, Color.Red, SymbolType.Diamond);
// Fill the symbols with white
myCurve.Symbol.Fill = new Fill(Color.White);
// Generate a blue curve with circle symbols, and "Acceleration" in the legend
myCurve = myPane.AddCurve("Acceleration",
aList, Color.Blue, SymbolType.Circle);
// Fill the symbols with white
myCurve.Symbol.Fill = new Fill(Color.White);
// Associate this curve with the Y2 axis
myCurve.IsY2Axis = true;
// Generate a green curve with square symbols, and "Distance" in the legend
myCurve = myPane.AddCurve("Distance",
dList, Color.Green, SymbolType.Square);
// Fill the symbols with white
myCurve.Symbol.Fill = new Fill(Color.White);
// Associate this curve with the second Y axis
myCurve.YAxisIndex = 1;
// Generate a Black curve with triangle symbols, and "Energy" in the legend
myCurve = myPane.AddCurve("Energy",
eList, Color.Black, SymbolType.Triangle);
// Fill the symbols with white
myCurve.Symbol.Fill = new Fill(Color.White);
// Associate this curve with the Y2 axis
myCurve.IsY2Axis = true;
// Associate this curve with the second Y2 axis
myCurve.YAxisIndex = 1;
// Show the x axis grid
myPane.XAxis.MajorGrid.IsVisible = true;
// Make the Y axis scale red
myPane.YAxis.Scale.FontSpec.FontColor = Color.Red;
myPane.YAxis.Title.FontSpec.FontColor = Color.Red;
// turn off the opposite tics so the Y tics don't show up on the Y2 axis
myPane.YAxis.MajorTic.IsOpposite = false;
myPane.YAxis.MinorTic.IsOpposite = false;
// Don't display the Y zero line
myPane.YAxis.MajorGrid.IsZeroLine = false;
// Align the Y axis labels so they are flush to the axis
myPane.YAxis.Scale.Align = AlignP.Inside;
myPane.YAxis.Scale.Max = 100;
// Enable the Y2 axis display
myPane.Y2Axis.IsVisible = true;
// Make the Y2 axis scale blue
myPane.Y2Axis.Scale.FontSpec.FontColor = Color.Blue;
myPane.Y2Axis.Title.FontSpec.FontColor = Color.Blue;
// turn off the opposite tics so the Y2 tics don't show up on the Y axis
myPane.Y2Axis.MajorTic.IsOpposite = false;
myPane.Y2Axis.MinorTic.IsOpposite = false;
// Display the Y2 axis grid lines
myPane.Y2Axis.MajorGrid.IsVisible = true;
// Align the Y2 axis labels so they are flush to the axis
myPane.Y2Axis.Scale.Align = AlignP.Inside;
myPane.Y2Axis.Scale.Min = 1.5;
myPane.Y2Axis.Scale.Max = 3;
// Create a second Y Axis, green
YAxis yAxis3 = new YAxis("Distance, m");
myPane.YAxisList.Add(yAxis3);
yAxis3.Scale.FontSpec.FontColor = Color.Green;
yAxis3.Title.FontSpec.FontColor = Color.Green;
yAxis3.Color = Color.Green;
// turn off the opposite tics so the Y2 tics don't show up on the Y axis
yAxis3.MajorTic.IsInside = false;
yAxis3.MinorTic.IsInside = false;
yAxis3.MajorTic.IsOpposite = false;
yAxis3.MinorTic.IsOpposite = false;
// Align the Y2 axis labels so they are flush to the axis
yAxis3.Scale.Align = AlignP.Inside;
Y2Axis yAxis4 = new Y2Axis("Energy");
yAxis4.IsVisible = true;
myPane.Y2AxisList.Add(yAxis4);
// turn off the opposite tics so the Y2 tics don't show up on the Y axis
yAxis4.MajorTic.IsInside = false;
yAxis4.MinorTic.IsInside = false;
yAxis4.MajorTic.IsOpposite = false;
yAxis4.MinorTic.IsOpposite = false;
// Align the Y2 axis labels so they are flush to the axis
yAxis4.Scale.Align = AlignP.Inside;
yAxis4.Type = AxisType.Log;
yAxis4.Scale.Min = 100;
// Fill the axis background with a gradient
myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45.0f);
zgc.AxisChange();
}
}
}
完整代码下载
标签:GraphPane,Color,ZedGraph,曲线,zedGraphControl1,new,myPane,axis,WinForm 来源: https://blog.csdn.net/zlbdmm/article/details/98742637