GDI+Windows VistaVisual Studio 2013Visual Studio 2005Windows XP.NET 2.0C# 2.0HTML中级开发Visual StudioWindows.NETC#
用于图形绘制的简单 C# 库






4.90/5 (246投票s)
一个用于快速简单绘制图表的 C# 库。
引言
在我们的应用程序中,我们必须显示一个多通道心电图 (ECG) 设备的输出。我查看了一些商业库,但它们都不能满足我的需求。因此,我决定自己设计一个简单的解决方案。
这是我尝试设计一个灵活、易于使用的绘图库。
该库能够以不同的布局显示多个图表。目前,可以显示五种模式
- Normal: 表示所有数据源显示在一个图表窗口中,带有单独的纵坐标。
- Stacked: 表示所有数据源显示在一个图表窗口中,垂直堆叠,共享纵坐标和横坐标。
- 垂直对齐:表示图表窗口垂直对齐显示,带有单独的纵坐标和共享的横坐标。
- 平铺水平:表示数据源在平铺窗口中显示(首选对齐方向为水平)。
- 平铺垂直:表示数据源在平铺窗口中显示(首选对齐方向为垂直)。
图表可以未缩放或自动缩放显示。在自动缩放模式下,可见图表将自动适应可见区域。
以下图像显示了不同显示模式的示例
正常
堆叠
水平平铺
垂直平铺
垂直对齐
X轴自动缩放
以下图像显示了一个心电图应用程序的示例,其中八个数据源垂直平铺并自动缩放显示。
Using the Code
该控件非常简单易用。只需查看示例应用程序即可。以下代码显示了演示应用程序中生成不同示例图表的部分
protected void CalcDataGraphs()
{
this.SuspendLayout();
display.DataSources.Clear();
display.SetDisplayRangeX(0, 400);
for (int j = 0; j < NumGraphs; j++)
{
display.DataSources.Add(new DataSource());
display.DataSources[j].Name = "Graph " + (j + 1);
display.DataSources[j].OnRenderXAxisLabel += RenderXLabel;
switch (CurExample)
{
case "NORMAL":
this.Text = "Normal Graph";
display.DataSources[j].Length = 5800;
display.PanelLayout = PlotterGraphPaneEx.LayoutMode.NORMAL;
display.DataSources[j].AutoScaleY = false;
display.DataSources[j].SetDisplayRangeY(-300, 300);
display.DataSources[j].SetGridDistanceY(100);
display.DataSources[j].OnRenderYAxisLabel = RenderYLabel;
CalcSinusFunction_0(display.DataSources[j], j);
break;
case "NORMAL_AUTO":
this.Text = "Normal Graph Autoscaled";
display.DataSources[j].Length = 5800;
display.PanelLayout = PlotterGraphPaneEx.LayoutMode.NORMAL;
display.DataSources[j].AutoScaleY = true;
display.DataSources[j].SetDisplayRangeY(-300, 300);
display.DataSources[j].SetGridDistanceY(100);
display.DataSources[j].OnRenderYAxisLabel = RenderYLabel;
CalcSinusFunction_0(display.DataSources[j], j);
break;
case "STACKED":
this.Text = "Stacked Graph";
display.PanelLayout = PlotterGraphPaneEx.LayoutMode.STACKED;
display.DataSources[j].Length = 5800;
display.DataSources[j].AutoScaleY = false;
display.DataSources[j].SetDisplayRangeY(-250, 250);
display.DataSources[j].SetGridDistanceY(100);
CalcSinusFunction_1(display.DataSources[j], j);
break;
case "VERTICAL_ALIGNED":
this.Text = "Vertical aligned Graph";
display.PanelLayout =
PlotterGraphPaneEx.LayoutMode.VERTICAL_ARRANGED;
display.DataSources[j].Length = 5800;
display.DataSources[j].AutoScaleY = false;
display.DataSources[j].SetDisplayRangeY(-300, 300);
display.DataSources[j].SetGridDistanceY(100);
CalcSinusFunction_2(display.DataSources[j], j);
break;
case "VERTICAL_ALIGNED_AUTO":
this.Text = "Vertical aligned Graph autoscaled";
display.PanelLayout =
PlotterGraphPaneEx.LayoutMode.VERTICAL_ARRANGED;
display.DataSources[j].Length = 5800;
display.DataSources[j].AutoScaleY = true;
display.DataSources[j].SetDisplayRangeY(-300, 300);
display.DataSources[j].SetGridDistanceY(100);
CalcSinusFunction_2(display.DataSources[j], j);
break;
case "TILED_VERTICAL":
this.Text = "Tiled Graphs (vertical prefered)";
display.PanelLayout = PlotterGraphPaneEx.LayoutMode.TILES_VER;
display.DataSources[j].Length = 5800;
display.DataSources[j].AutoScaleY = false;
display.DataSources[j].SetDisplayRangeY(-300, 600);
display.DataSources[j].SetGridDistanceY(100);
CalcSinusFunction_2(display.DataSources[j], j);
break;
case "TILED_VERTICAL_AUTO":
this.Text = "Tiled Graphs (vertical prefered) autoscaled";
display.PanelLayout = PlotterGraphPaneEx.LayoutMode.TILES_VER;
display.DataSources[j].Length = 5800;
display.DataSources[j].AutoScaleY = true;
display.DataSources[j].SetDisplayRangeY(-300, 600);
display.DataSources[j].SetGridDistanceY(100);
CalcSinusFunction_2(display.DataSources[j], j);
break;
case "TILED_HORIZONTAL":
this.Text = "Tiled Graphs (horizontal prefered)";
display.PanelLayout = PlotterGraphPaneEx.LayoutMode.TILES_HOR;
display.DataSources[j].Length = 5800;
display.DataSources[j].AutoScaleY = false;
display.DataSources[j].SetDisplayRangeY(-300, 600);
display.DataSources[j].SetGridDistanceY(100);
CalcSinusFunction_2(display.DataSources[j], j);
break;
case "TILED_HORIZONTAL_AUTO":
this.Text = "Tiled Graphs (horizontal prefered) autoscaled";
display.PanelLayout = PlotterGraphPaneEx.LayoutMode.TILES_HOR;
display.DataSources[j].Length = 5800;
display.DataSources[j].AutoScaleY = true;
display.DataSources[j].SetDisplayRangeY(-300, 600);
display.DataSources[j].SetGridDistanceY(100);
CalcSinusFunction_2(display.DataSources[j], j);
break;
case "ANIMATED_AUTO":
this.Text = "Animated graphs fixed x range";
display.PanelLayout = PlotterGraphPaneEx.LayoutMode.TILES_HOR;
display.DataSources[j].Length = 402;
display.DataSources[j].AutoScaleY = false;
display.DataSources[j].AutoScaleX = true;
display.DataSources[j].SetDisplayRangeY(-300, 500);
display.DataSources[j].SetGridDistanceY(100);
display.DataSources[j].XAutoScaleOffset = 50;
CalcSinusFunction_3(display.DataSources[j], j, 0);
display.DataSources[j].OnRenderYAxisLabel = RenderYLabel;
break;
}
}
ApplyColorSchema();
this.ResumeLayout();
display.Refresh();
}
函数 CalcSinusFunction_0
CalcSinusFunction_1
和 CalcSinusFunction_2
用于计算图表中不同的正弦函数
protected void CalcSinusFunction_0(DataSource src, int idx)
{
for (int i = 0; i < src.Length; i++)
{
src.Samples[i].x = i;
src.Samples[i].y = (float)(((float)200 * Math.Sin((idx + 1) *(
i + 1.0) * 48 / src.Length)));
}
}
函数 RenderYLabel
和 RenderXLabel
用于渲染图表的 X 和 Y 轴标签。
private String RenderXLabel(DataSource s, int idx)
{
if (s.AutoScaleX)
{
int Value = (int)(s.Samples[idx].x );
return "" + Value;
}
else
{
int Value = (int)(s.Samples[idx].x / 200);
String Label = "" + Value + "\"";
return Label;
}
}
private String RenderYLabel(DataSource s, float value)
{
return String.Format("{0:0.0}", value);
}
摘要
这里有很多可以调整的参数,但这里没有解释 - 只要看看代码。这个库远未完成,但它是一个很好的起点。代码简单且自解释。从这里开始,很容易根据您的需要改编代码。
我从这里获得了如此多的输入,我想回馈一些东西。所以,这是我在 Code Project 上的第一篇文章。我希望你喜欢它。
待办事项
- 代码清理。
版本历史
- 2014 年 9 月 4 日 - 4 年来的第一次更新。重新发现了我的代码 ;-) 将解决方案升级到 VS 2013 Express。清理了一些魔数。 更多内容即将推出 ;-)
- 2009 年 7 月 12 日 - 更新文章。
- 2009 年 2 月 12 日 - 实现了 x 轴自动缩放。
- 2009 年 1 月 28 日 - 更多清理。实现了打印表单。
- 2009 年 1 月 27 日 - 新的显示模式,一些清理。
- 2009 年 1 月 25 日 - 初始发布。