C#折线图控件使用方法详解

Tina ·
更新时间:2024-11-13
· 1285 次阅读

本文实例为大家分享了C#编写折线图控件的具体代码,供大家参考,具体内容如下

简单解说

这是第一次写博客,也是第一次发布自己写代码,有不足之处请多见谅。
源代码参考了网络搜索到的一些资源。
因为我需要的折线图数据没有小于0的,所以在计算时偷懒了。只支持大于0的数据。

上图

如何插入一段漂亮的代码片
因为自学编程,代码注释与命名比较乱,请见谅。
这是新建控件的代码。需要给控件添加FoldLineDiagram_Resize 事件。

using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace vc_farm {     /// <summary>     /// 折线图控件     /// 注意:     /// 1、数据列最少不小于2列。     /// 2、数据列与数据标题列长度必须保持一致     /// 3、数据标题长度最大为100     /// 4、折线数量不能大于10个     /// </summary>     public partial class FoldLineDiagram : UserControl     {         private Bitmap mImage;              //画的折线图         private FoldLineData mData;         //记录折线数据,在窗口大小改变时可重新计算         private List<SelectionArea> mSelectionArea = new List<SelectionArea>();     //可选择区域【此处无用,原用作记录数据点,方便判断光标是否选中某条数据折线】         private SelectionArea mNowSelectionArea;        //当前选中的区域【此处无用】         public FoldLineDiagram()         {             InitializeComponent();         }         #region 禁止基类属性显示         [Browsable(false)]         [EditorBrowsable(EditorBrowsableState.Never)]         public override Image BackgroundImage         {             get { return base.BackgroundImage; }             set { base.BackgroundImage = value; }         }         #endregion         /// <summary>         /// 获取折线图片(只有使用了ShowFoldLineDiagram方法后才能正确获取)         /// </summary>         public Bitmap Image         {             get { return mImage; }         }         /// <summary>         /// 显示折线         /// </summary>         /// <param name="aData">折线数据对象</param>         public void ShowFoldLineDiagram(FoldLineData aData)         {             this.mData = aData;             mImage = CreateImageS(aData);             this.BackgroundImage = new Bitmap(mImage);      //背景为复制的图片             //this.BackgroundImageLayout = ImageLayout.Stretch;   //拉伸显示显示         }         /// <summary>         /// 保存 折线图 图片(只有使用了ShowFoldLineDiagram方法后才能正确保存)         /// </summary>         /// <param name="aSavePath">保存文件的路径</param>         /// <param name="aImageFormat">保存的格式</param>         public void SaveImage(string aSavePath, System.Drawing.Imaging.ImageFormat aImageFormat)         {             new Bitmap(mImage).Save(aSavePath, aImageFormat);         }         private Bitmap CreateImageS(FoldLineData data)         {             #region 数据验证             if (data.DataTitleText.Count <= 1) return null;                     //限制列数不能小于2             if (data.DataTitleText.Count >100) return null;                     //限制列数不能大于100             if (data.listFoldLineDataStyle.Count > 10) return null;             //限制折线数量不能大于10             int temp = data.DataTitleText.Count;                                //获取数据标题长度             for (int i = 0; i < data.listFoldLineDataStyle.Count; i++)          //循环所有数据             {                 if (data.listFoldLineDataStyle[i].Data.Count !=temp)            //当前数据长度  与数据标题长度不一致                 {                     return null;                 }             }             #endregion             #region 函数内部变量赋值             this.mSelectionArea.Clear();                            //记录数据清空             int height = this.Height, width = this.Width;                      //设置图片大小             //设置左右上下边框距离图片边框间距             int left = (int)(width * 0.1);             int right = (int)(width * 0.1);             int top = (int)(height * 0.1);             int bottom;             if (data.ShowLegend == true) bottom = (int)(height * 0.15);          //显示图例时,下边框为0.2             else bottom = (int)(height * 0.1);                 #endregion             Bitmap image = new Bitmap(width, height);           //新建一张图片             Graphics g = Graphics.FromImage(image);             g.SmoothingMode = SmoothingMode.AntiAlias;  //使绘图质量最高,即消除锯齿             g.InterpolationMode = InterpolationMode.HighQualityBicubic;             g.CompositingQuality = CompositingQuality.HighQuality;             try             {                 #region 绘图准备工作                 g.Clear(Color.White);                           //清空图片背景色                 Font font = data.DataTitleTextFont;         //设置 X与Y轴  标题字体                 Font font1 = data.FoldLineTextFont;        //设置 标题  字体                 //Font font2 = aLineDataFont;        //设置 数据显示  字体                 LinearGradientBrush brush = new LinearGradientBrush(                 new Rectangle(0, 0, image.Width, image.Height), data.BackgroundBorderColor, data.BackgroundBorderColor, 1.2f, true);                 g.FillRectangle(Brushes.AliceBlue, 0, 0, width, height);                 #endregion                 #region 画折线图标题                 Brush brush1 = new SolidBrush(data.FoldLineTextColor);                 SizeF sizeF = g.MeasureString(data.FoldLineText, font1);             //计算标题文字大小                 g.DrawString(data.FoldLineText, font1, brush1, (width - sizeF.Width) / 2, (top - sizeF.Height) / 2);             //画标题                 #endregion                 #region 绘制框线                 //画图片的边框线                 g.DrawRectangle(new Pen(data.BackgroundBorderColor), 0, 0, image.Width - 1, image.Height - 1);                 Pen mypen = new Pen(brush, 1);              //边框线画笔                 //绘制纵向线条                 int xLineSpacing = (width - left - right) / (data.DataTitleText.Count - 1);            //计算X轴 线条间距                 int xPosition = left;                                               //X轴开始位置                 for (int i = 0; i < data.DataTitleText.Count; i++)                 {                     g.DrawLine(mypen, xPosition, top, xPosition, height - bottom);                   //画X轴竖线                     sizeF = g.MeasureString(data.DataTitleText[i], font);             //计算X轴文字大小                     g.DrawString(data.DataTitleText[i], font, new SolidBrush(data.DataTitleTextColor), xPosition - (sizeF.Width / 2), height - bottom  + 5); //设置文字内容及输出位置                     xPosition += +xLineSpacing;        //累加间距                 }                 //Pen mypen1 = new Pen(Color.Blue, 3);                 xPosition = left;                 g.DrawLine(mypen, xPosition, top, xPosition, height - bottom);                                   //画X轴第1条线(粗线)                 //绘制横向线条                 List<int> yName = ReckonYLine(data.listFoldLineDataStyle);                 int mLineCount = yName.Count;                                    //计算Y轴行数                 int yLineSpacing = (height - bottom - top) / (yName.Count - 1);           //计算Y轴 线条间距                 int yPosition = height - bottom;                                                //Y轴开始点                 for (int i = 0; i < yName.Count; i++)                 {                     g.DrawLine(mypen, left, yPosition, width - right, yPosition);                     sizeF = g.MeasureString(yName[i].ToString(), font);                     g.DrawString(yName[i].ToString(), font, new SolidBrush(data.DataTitleTextColor), left - sizeF.Width - 5, yPosition - (sizeF.Height / 2)); //设置文字内容及输出位置                     yPosition -= yLineSpacing;                 }                 yPosition = height - bottom;                 g.DrawLine(mypen, left, yPosition, width - right, yPosition);      //Y轴最下面一天线加粗                 #endregion                 #region 画折线,及数据                 for (int i = 0; i < data.listFoldLineDataStyle.Count; i++)                 {                     //显示折线效果                     Pen mypen2 = new Pen(data.listFoldLineDataStyle[i].FoldLineColor, 2);         //折线画笔                     List<int> pointData = data.listFoldLineDataStyle[i].Data;                       //取出折线数据                     xPosition = left;                     float yMultiple = (float)(height - top - bottom) / (float)yName.Max();            //计算Y轴比例因子                     List<Point> linePoint = new List<Point>();                      //定义折线节点坐标                     for (int j = 0; j < pointData.Count; j++)                     {                         Point point = new Point();                         point.X = xPosition;                         point.Y = top + (int)((yName.Max() - pointData[j]) * yMultiple);                         xPosition += xLineSpacing;                         linePoint.Add(point);                         g.FillEllipse(new SolidBrush(data.listFoldLineDataStyle[i].FoldLineColor), point.X - 5, point.Y - 5, 10, 10);           //画节点的圆点                         g.DrawString(pointData[j].ToString(), data.listFoldLineDataStyle[i].FoldLineDataFont, new SolidBrush(data.listFoldLineDataStyle[i].FoldLineDataColor), point.X, point.Y + 10);       //绘制节点文字                     }                     g.DrawLines(mypen2, linePoint.ToArray()); //绘制折线                      //记录画图区域                     SelectionArea sa = new SelectionArea();                     sa.linePoint = linePoint;                     //sa.rect = new Rectangle();                     this.mSelectionArea.Add(sa);                 }                 #endregion                 #region 画图例                 if (data.ShowLegend ==true)                 {                     int length = 0;         //绘制的长度                     for (int i = 0; i < data.listFoldLineDataStyle.Count; i++)                     {                         //显示折线效果                         Pen mypen2 = new Pen(data.listFoldLineDataStyle[i].FoldLineColor, 2);         //折线画笔                         if (data.listFoldLineDataStyle[i].DataName == "折线")                         {                             data.listFoldLineDataStyle[i].DataName += i.ToString(); //如果是默认名称,则给默认名称加数字                         }                         sizeF = g.MeasureString(data.listFoldLineDataStyle[i].DataName, data.DataTitleTextFont);       //计算字体长度                         //20:两个图例的间距,30:图例中颜色表示区宽度 ,10:图例颜色标识区与文本区间距                         length += 20 + 30 + 10 + (int)sizeF.Width;                     }                     length += 20;   //加上最后的间距                     int startX = (width - length) / 2;                     int startY = (int)(height * 0.92);                     for (int i = 0; i < data.listFoldLineDataStyle.Count; i++)                     {                         //显示折线效果                         Pen mypen2 = new Pen(data.listFoldLineDataStyle[i].FoldLineColor, 2);         //折线画笔                         if (data.listFoldLineDataStyle[i].DataName == "折线")                         {                             data.listFoldLineDataStyle[i].DataName += i.ToString(); //如果是默认名称,则给默认名称加数字                         }                         sizeF = g.MeasureString(data.listFoldLineDataStyle[i].DataName, data.DataTitleTextFont);       //计算字体长度                         g.FillRectangle(new SolidBrush(data.listFoldLineDataStyle[i].FoldLineColor), startX, startY, 30, 10); //绘制小矩形                         g.DrawString(data.listFoldLineDataStyle[i].DataName, data.DataTitleTextFont, new SolidBrush(data.listFoldLineDataStyle[i].FoldLineColor), startX  + 30 + 10, startY);                         startX += 30 + 10 + (int)sizeF.Width+20;                         //记录画图区域的 图例显示区域                         Rectangle rect = new Rectangle(startX, startY, 30, 10);                         SelectionArea sa = this.mSelectionArea[i];                         sa.rect = rect;                         this.mSelectionArea[i] = sa;                     }                 }                 #endregion                 return new Bitmap(image);             }             finally             {                 g.Dispose();                 image.Dispose();             }         }         /// <summary>         /// Y轴横线 及 Y轴标题内如 计算          /// </summary>         /// <param name="data"></param>         /// <returns></returns>         private List<int> ReckonYLine(List<FoldLineDataStyle> flData)         {             List<int> AllData = new List<int>();        //所有数据汇总在一起              foreach (FoldLineDataStyle item in flData)             {                 AllData.AddRange(item.Data);             }             //定义最大值与最小值             int max = AllData.Max();             int min = AllData.Min();             List<int> yName = new List<int>();             int csMax = 0;       //测算上限             /*如果需要增加小于0数据判断,则需要在此次增加一些判断。             *就是取最小值,判断是否为负数,是则取绝对值进行计算,不是则和现在计算方式一样             */             if (max.ToString().Length > 1)        //如果大于9             {                 //测算最大上限值                 string ling = "";                 for (int i = 0; i < max.ToString().Length - 1; i++)                    //为数字末尾补0                     ling += "0";                 string temp = max.ToString().Substring(0, 1);           //取出最高位数字                 csMax = Int32.Parse((Int32.Parse(temp) + 1) + ling);   //如果max=75162 则转成 80000                 for (int i = 0; i <= (Int32.Parse(temp) + 1); i++)                 {                     yName.Add((Int32.Parse(i + ling)));                 }             }             else             {                 csMax = max + 1;                 for (int i = 0; i <= csMax; i++)                 {                     yName.Add(i);                 }             }             return yName;         }         private void FoldLineDiagram_Resize(object sender, EventArgs e)         {             if (mData!=null)             {                 mImage = CreateImageS(mData);                 this.BackgroundImage = new Bitmap(mImage);      //背景为复制的图片             }         }         /// <summary>         /// 选择区域         /// </summary>         private struct SelectionArea         {             /// <summary>             /// 选择区域             /// </summary>             public Rectangle rect;             /// <summary>             /// 折线区域             /// </summary>             public List<Point> linePoint;            }         /// <summary>         /// 判断点是否在矩形范围内         /// </summary>         /// <param name="rect"></param>         /// <param name="pt"></param>         /// <returns></returns>         public static bool IsPointIn(RectangleF rect, PointF pt)         {             if (pt.X >= rect.X && pt.Y >= rect.Y && pt.X <= rect.X + rect.Width && pt.Y <= rect.Y + rect.Height)             {                 return true;             }             else return false;         }     }     /// <summary>     /// 折线背景设置     /// </summary>     public class FoldLineData     {         /// <summary>         /// 全部折线    默认:空数据         /// </summary>         public List<FoldLineDataStyle> listFoldLineDataStyle;         /// <summary>         /// 折线图的标题文本    默认:空文本         /// </summary>         public List<string> DataTitleText;         /// <summary>         /// 折线图的标题文本    默认:空文本         /// </summary>         public string FoldLineText;         /// <summary>         /// 折线图的标题文本 字体颜色    默认:黑色         /// </summary>         public Color FoldLineTextColor;         /// <summary>         /// 折线图的标题文本 字体格式    默认:"宋体", 20         /// </summary>         public Font FoldLineTextFont;         /// <summary>         /// 数据列标题 字体颜色    默认:黑色         /// </summary>         public Color DataTitleTextColor;         /// <summary>         /// 数据列标题 字体格式    默认:"宋体", 9         /// </summary>         public Font DataTitleTextFont;         /// <summary>         /// 背景边框线 颜色    默认:深灰色         /// </summary>         public Color BackgroundBorderColor;         /// <summary>         /// 显示图例    默认:true         /// </summary>         public bool ShowLegend;         /// <summary>         /// 构造函数         /// </summary>         /// <param name="flds">数据组。每组数据长度必须一致,且与数据列名称长度一致</param>         /// <param name="dataTitleText">数据列名称</param>         public FoldLineData(List<FoldLineDataStyle> flds, List<string> dataTitleText)         {             DataTitleText = dataTitleText;             listFoldLineDataStyle = flds;             FoldLineText = "";             FoldLineTextColor = Color.Black;             FoldLineTextFont = new System.Drawing.Font("宋体", 20, FontStyle.Regular);             DataTitleTextColor = Color.Black;             DataTitleTextFont = new System.Drawing.Font("Arial", 9, FontStyle.Regular);             BackgroundBorderColor = Color.DarkGray;             ShowLegend = true;         }     }     /// <summary>     /// 折线数据及样式     /// </summary>     public class FoldLineDataStyle     {         /// <summary>         /// 折线数据    默认:null         /// </summary>         public List<int> Data;         /// <summary>         /// 折线数据名称    默认:折线         /// </summary>         public string DataName;         /// <summary>         /// 折线颜色    默认:红色         /// </summary>         public Color FoldLineColor;         /// <summary>         /// 折线点上 显示的数据颜色    默认:红色         /// </summary>         public Color FoldLineDataColor;         /// <summary>         /// 折线点上 显示的数据字体格式    默认:"宋体", 8         /// </summary>         public Font FoldLineDataFont;         /// <summary>         /// 构造函数         /// </summary>         /// <param name="data">数据。数据长度一定需要保持一致</param>         public FoldLineDataStyle(List<int> data)         {             Data = data;             FoldLineColor = Color.Red;             FoldLineDataColor = Color.Red;             FoldLineDataFont = new System.Drawing.Font("宋体", 9, FontStyle.Regular);             DataName = "折线";         }     } }

测试数据代码

private void Form2_Load(object sender, EventArgs e)         {             List<string> name = new List<string> { "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月" };             List<int> data = new List<int> { 1150, 250, 1550, 1600, 1800, 900, 2500, 1700 };             List<int> data1 = new List<int> { 1250, 2250, 3550, 1600, 800, 900, 500, 2700 };             List<int> data2 = new List<int> { 2150, 250, 1550, 1600, 1700, 900, 200, 1700 };             FoldLineDataStyle fld = new FoldLineDataStyle(data);    //默认格式             FoldLineDataStyle fld1 = new FoldLineDataStyle(data1);             fld1.DataName = "测试数据1";             fld1.FoldLineColor = Color.Green;             fld1.FoldLineDataColor = Color.Green;             FoldLineDataStyle fld2 = new FoldLineDataStyle(data2);             //fld2.DataName = "测试数据1";             fld2.FoldLineColor = Color.Blue;             fld2.FoldLineDataColor = Color.Blue;             FoldLineData foldLineData = new FoldLineData(new List<FoldLineDataStyle> { fld, fld1, fld2 }, name);             foldLineData.ShowLegend = true;             foldLineData.FoldLineText = "测试折线图";             this.foldLineDiagram1.ShowFoldLineDiagram(foldLineData);         }



折线图 C# 方法

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章