C#生成饼形图及添加文字说明实例代码
程序员文章站
2024-02-20 14:42:40
本文以实例形式说明了c#生成饼形图,圆饼图,并为图表添加文字注释的方法。可实现文字显示在图表周围,直观形象的展示各个数据分量的走抛情况的效果。通常在编写系统报表过程中,使用...
本文以实例形式说明了c#生成饼形图,圆饼图,并为图表添加文字注释的方法。可实现文字显示在图表周围,直观形象的展示各个数据分量的走抛情况的效果。通常在编写系统报表过程中,使用图表显示数据是很多人认可的方式。本文所述的就是一个用visual c#生成圆饼型图表,并且在图表外围添加数据分量报表说明的一个例子。
具体功能代码如下:
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; namespace 在饼型图的外围显示说明文字 { public partial class form1 : form { public form1() { initializecomponent(); } public static string[] xtext = new string[7] { "商品1", "商品2", "商品3", "商品4", "商品5", "商品6", "商品7" };//存储数据的名称数组 public static float[] szdata = new float[7] { 5f, 17f, 7f, 2f, 10f, 5f, 4f };//获取每列的和 public static color[] wearcolor = new color[] { color.red,color.gold,color.chartreuse,color.teal,color.royalblue,color.fuchsia,color.firebrick, color.goldenrod,color.forestgreen,color.aqua,color.blue,color.palevioletred,color.salmon,color.yellow,color.limegreen,color.lightblue,color.lightsteelblue,color.mediumpurple}; public static string[] areatext;//临时存储数据的名称数组 pen mypen; float areaangle = 0f; public static float xsize = 50;//x轴的大小 public static float ysize = 50;//y轴的大小 public static float asum=50;//记录饼形的总和 public static float temxsize = 0;//x轴的临时大小 public static float xleft = 0;//x轴的左端点 public static float xright = 0;//x轴的右端点 public static float yup = 0;//y轴的上端点 public static float ydown = 50;//y轴的下端点 public static solidbrush mybrush = new solidbrush(color.red); public static float aline = 20;//标识文字的前端线长 public static float asash = 3;//标识文本名边框的宽度 public static float temxleft = 0;//x轴的左端点初始化 #region 绘制饼形图(area) public static float areaxmaxwidth = 0;//获取字符串的宽度 public static float areaxmaxheight = 0;//获取字符串的高度 //获取饼形图的标识文字 public void areavalue() { string temtextsize = "";//存储最长的名称 font lsfont = new system.drawing.font("宋体", 8);//设置说明文字的字体 areatext = new string[xtext.length];//实例化一个临时数组 for (int i = 0; i < areatext.length; i++)//获取名称 { areatext[i] = xtext[i]; } float aresf = 0;//记录百分比 for (int i = 0; i < areatext.length; i++)//通过名称及百分比,组合说明文字 { aresf = (szdata[i] / asum) * 100;//获取当前记录的百分比 aresf = (float)math.round(aresf, 3);//对百分比进行四舍五入 areatext[i] = areatext[i] + " " + aresf.tostring() + "%";//组合说明文字 if (areatext[i].length > temtextsize.length)//获取最长的说明文件 temtextsize = areatext[i]; } graphics titg = this.creategraphics();//创建graphics类对象 sizef xmaxsize = titg.measurestring(temtextsize + asash * 2, lsfont);//将绘制的字符串进行格式化 areaxmaxwidth = xmaxsize.width;//获取字符串的宽度 areaxmaxheight = xmaxsize.height;//获取字符串的高度 } //绘制饼形图表 public void protractarea(graphics g) { areavalue();//计算最长说明文字的大小 //初始化变量 mypen = new pen(color.black, 1);//设置画笔的颜色及大小 float f = 0;//记录百分比 float timenum = 0;//扇形的绘制度数 float axleft = 0;//设置饼形图的x坐标 float ayup = 0;//设置饼形图的y坐标 float axsize = 0;//设置饼形图的宽度 float aysize = 0;//设置饼形图的高度 float atop = 0;//记录饼形的高度为长和宽的最小值 float aleft = 0;//记录饼形的高度为长和宽的最小值 timenum = areaangle;//设置饼形图的起始度数 //计算饼形图的初始位置 xleft = panel1.width - (panel1.width - 5);//去了边框后饼形图的x位置 xsize = panel1.width - 10;//设置饼形图的宽度 temxleft = axleft;//记录饼形图的x坐标 axleft = xleft;//记录饼形图的x坐标 axsize = xsize;//记录饼形图的宽度 //通过说明文字的大小计算饼形图的位置 axleft = axleft + areaxmaxwidth + aline;//设置去除说明文字后的饼形图x坐标 ayup = ayup + areaxmaxheight;//设置去除说明文字后的饼形图y坐标 axsize = xsize - areaxmaxwidth * 2 - aline * 2;//设置去除说明文字后的饼形图宽度 aysize = ysize - areaxmaxheight * 2;//设置去除说明文字后的饼形图高度 if (axsize >= aysize)//如果饼形图的宽度大于等于高度 { aleft = axsize - aysize;//记录饼形图的x坐标 axsize = aysize;//将高度设为宽度 } else { atop = aysize - axsize;//记录饼形图的y坐标 aysize = axsize;//将宽度设为高度 } if (aleft != 0)//如果宽大于高 { axleft = axleft + aleft / 2;//设置饼形图横向局中 } if (atop != 0)//如果高大于宽 { ayup = ayup + atop / 2;//设置饼形图纵向局中 } temxleft = xleft; //绘制饼形图 if (axsize > 0 && aysize > 0)//如果饼形图的宽和高大于0 { for (int i = 0; i < szdata.length; i++)//遍历数据 { f = szdata[i] / asum;//获取当前数据的百分比 //设置当前扇形图的填充颜色 if (i >= wearcolor.length)//如果没有超出颜色数组 mybrush = new solidbrush(wearcolor[i - wearcolor.length]); else mybrush = new solidbrush(wearcolor[i]); g.fillpie(mybrush, axleft, ayup, axsize, aysize, timenum, f * 360);//绘制扇形图 timenum += f * 360;//设置下一个扇形图的度数 } proareasign(g);//绘制饼形图的说明文字 } else return; } #endregion #region 绘制饼形图标识(area) public void proareasign(graphics g) { areavalue();//存储最长的名称 mypen = new pen(color.black, 1);//设置画笔的颜色及大小 font lsfont = new system.drawing.font("宋体", 8);//设置说明文字的字体样式 solidbrush zbrush = new solidbrush(color.black);//设置存放说明文字边框的画刷 solidbrush atbrush = new solidbrush(color.khaki);//设置存放说明文字方块的背景画刷 //初始化变量 float f = 0;//记录百分比 float timenum = 0;//扇形的绘制度数 float axleft = 0;//设置饼形图的x坐标 float ayup = 0;//设置饼形图的y坐标 float axsize = 0;//设置饼形图的宽度 float aysize = 0;//设置饼形图的高度 float atop = 0;//记录饼形的高度为长和宽的最小值 float aleft = 0;//记录饼形的高度为长和宽的最小值 graphics titg = panel1.creategraphics();//创建graphics类对象 sizef xmaxsize = titg.measurestring("", lsfont);//将绘制的字符串进行格式化 float swidth = 0;//获取字符串的宽度 float sheight = 0;//获取字符串的高度 //计算饼形图的初始位置 xleft = panel1.width - (panel1.width - 5);//去了边框后饼形图的x位置 xsize = panel1.width - 10;//设置饼形图的宽度 temxleft = axleft;//记录饼形图的x坐标 axleft = xleft;//记录饼形图的x坐标 axsize = xsize;//记录饼形图的宽度 //通过说明文字的大小计算饼形图的位置 axleft = axleft + areaxmaxwidth + aline;//设置去除说明文字后的饼形图x坐标 ayup = ayup + areaxmaxheight;//设置去除说明文字后的饼形图y坐标 axsize = xsize - areaxmaxwidth * 2 - aline * 2;//设置去除说明文字后的饼形图宽度 aysize = ysize - areaxmaxheight * 2;//设置去除说明文字后的饼形图高度 if (axsize >= aysize)//如果饼形图的宽度大于等于高度 { aleft = axsize - aysize;//记录饼形图的x坐标 axsize = aysize;//将高度设为宽度 } else { atop = aysize - axsize;//记录饼形图的y坐标 aysize = axsize;//将宽度设为高度 } if (aleft != 0)//如果宽大于高 { axleft = axleft + aleft / 2;//设置饼形图横向局中 } if (atop != 0)//如果高大于宽 { ayup = ayup + atop / 2;//设置饼形图纵向局中 } temxleft = xleft; //初始化说明文字前横线的变量 float x1 = 0; float y1 = 0; float x2 = 0; float y2 = 0; //初始化说明文字位置的变量 float tx1 = 0; float ty1 = 0; float tx2 = 0; float ty2 = 0; float temf = 0;//记录百分比 double radians = 0;//记录扇形的角度 temf = (this.areaangle * (asum / 360) / asum);//记录起始位置的度数 timenum = this.areaangle;//记录扇形的起始角度 //绘制说明文字 if (axsize > 0 && aysize > 0) { for (int i = 0; i < szdata.length; i++)//遍历所有说明文字 { f = szdata[i] / asum;//获取当前记录的百分比 if (f == 0)//如果当前值为0 continue;//执行下一次循环 radians = ((double)((temf + f / 2) * 360) * math.pi) / (double)180; x1 = convert.tosingle(axleft + (axsize / 2.0 + (int)((float)(axsize / 2.0) * math.cos(radians)))); y1 = convert.tosingle(ayup + (aysize / 2.0 + (int)((float)(aysize / 2.0) * math.sin(radians)))); xmaxsize = titg.measurestring(areatext[i].trim(), lsfont);//将绘制的字符串进行格式化 swidth = xmaxsize.width;//获取字符串的宽度 sheight = xmaxsize.height;//获取字符串的高度 if ((temf + f / 2) * 360 > 90 && (temf + f / 2) * 360 <= 270) { x2 = x1 - aline; tx1 = x2 - 1 - swidth; ty1 = y1 - sheight / 2 - asash; tx2 = swidth; ty2 = sheight + asash * 2; g.fillrectangle(atbrush, tx1, ty1, tx2, ty2);//绘制内矩形 g.drawrectangle(new pen(color.black, 1), tx1, ty1, tx2, ty2);//绘制矩形 g.drawstring(areatext[i].trim(), lsfont, zbrush, new pointf(x2 - swidth + asash - 1, y1 - sheight / 2)); } else { x2 = x1 + aline; tx1 = x2 + 1; ty1 = y1 - sheight / 2 - asash; tx2 = swidth; ty2 = sheight + asash * 2; g.fillrectangle(atbrush, tx1, ty1, tx2, ty2);//绘制内矩形 g.drawrectangle(new pen(color.black, 1), tx1, ty1, tx2, ty2);//绘制矩形 g.drawstring(areatext[i].trim(), lsfont, zbrush, new pointf(x2 + asash + 1, y1 - sheight / 2)); } y2 = y1; g.drawline(new pen(new solidbrush(color.black), 1), x1, y1, x2, y2); timenum += f * 360; temf = temf + f; } } else return; } #endregion private void panel1_paint(object sender, painteventargs e) { xsize = panel1.width;//x轴的大小 ysize = panel1.height;//y轴的大小 ydown = panel1.height;//y轴的下端点 protractarea(e.graphics); } private void form1_load(object sender, eventargs e) { } } }
本例附有详细的注释说明,相信不难理解,读者还可以对其进行功能的修改或扩展,以实现更丰富的图文表现形式。