欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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)
    {

    }
  }
}

本例附有详细的注释说明,相信不难理解,读者还可以对其进行功能的修改或扩展,以实现更丰富的图文表现形式。