由於項目的原因,需要在WinForm上做出一個餅形統計圖的展示效果。相關數據是動態從數據庫中獲取,相應所占圓的角度計算都不是難點,可以很快地做出一個餅形統計圖。
但難點在於如何將一些介紹文字插入到相應的弧度上。
實現的效果如下圖所示:
相應的代碼如下:
/*3個參數
type:是指需要寫柱形圖,還是餅形圖,后面有個相應的判斷
StartTime:是指統計開始時間
EndTime:是指統計結束時間 */ private void Create_Chart(string type, DateTime StartTime, DateTime EndTime) { /*定義3個動態數組,分別儲存選項,選項對應數量,選項對應百分比,選項對應的餅圖角度,選項累積的總數*/ ArrayList arraylist_type = new ArrayList(); ArrayList arraylist_count = new ArrayList(); ArrayList arraylist_tp = new ArrayList(); ArrayList arraylist_angle = new ArrayList(); /*定義2個int變量,分別儲存統計總量,統計的總行數*/ int sum = 0; int resultCount = 0; /*取數據庫中的選項,對應數量
在這里,我采用的Linq 取數據庫中的數據,大家如果采用SQL語句的話,直接從數據庫操作層返回一個DataSet就可以了,方式類似*/ using (BLLUser a = new BLLUser()) { IList<Unit.HandleCountClass> result = a.Statistics_Handle(type, StartTime, EndTime); resultCount = result.Count; foreach (var item in result) { arraylist_type.Add(item.type.ToString()); arraylist_count.Add(Convert.ToInt32(item.Handlecount)); sum = sum + item.Handlecount; } } //聲明寬和高 int width = 470, height = 470; //創建1個Bitmap對象 Bitmap bitmap = new Bitmap(width, height); Graphics g = Graphics.FromImage(bitmap); //使用Clear方法使畫布為白色 g.Clear(Color.White); //抗鋸齒 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //高質量的文字 g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; //像素均偏移0.5個單位,以消除鋸齒 g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; //創建2個畫筆對象 Brush brush1 = new SolidBrush(Color.Black); Brush brush2 = new SolidBrush(Color.Orange); Brush brush3 = new SolidBrush(Color.White); //創建Font對象 Font font1 = new Font("Arial", 8); /*計算每個選項所占的百分比*/ for (int i = 0; i < resultCount; i++) { arraylist_tp.Add(Convert.ToSingle(Convert.ToSingle(arraylist_count[i]) * 100 / Convert.ToSingle(sum))); } /*Bar Chart為畫柱形圖*/ if (com_chart.Text == "Bar Chart") { //繪制顯示文字、柱形圖 for (int i = 0; i < resultCount; i++) { g.DrawString(arraylist_type[i].ToString() + " :", font1, brush1, new Point(20, 10 + i * 30)); g.FillRectangle(brush2, 130, 10 + i * 30, Convert.ToSingle(arraylist_tp[i]), 17); g.DrawString(arraylist_count[i].ToString() + "條 , " +
arraylist_tp[i].ToString() + "%", font1, brush1, new Point(135 + Convert.ToInt32(arraylist_tp[i]), 10 + i * 30)); } } /*Pie Chart為畫餅形圖*/ else if (com_chart.Text == "Pie Chart") { const double T = 3.14; /*Π的常量值*/ double halfangle = 0.0; int piex = 100, piey = 100, piew = 250, pieh = 250; /*計算每個選項所占餅形圖的角度*/ for (int i = 0; i < resultCount; i++) { arraylist_angle.Add(Convert.ToSingle(360/Convert.ToSingle(sum)) * Convert.ToSingle(arraylist_count[i])); } //繪制餅形圖 for (int i = 0; i < resultCount; i++) { float tem_angle = 0; for (int j = 0; j < i; j++) { tem_angle = tem_angle + Convert.ToSingle(arraylist_angle[j]); }
/*Get_Color(),是一個循環取色的方法,代碼在后面*/ g.FillPie(new SolidBrush(Get_Color(i)),piex,piey,piew,pieh,tem_angle,Convert.ToSingle(arraylist_angle[i])); /*以下是對四個象限、以及對90度、180度、270度和360度的判斷*/ if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 < 90) { halfangle = tem_angle + (Convert.ToSingle(arraylist_angle[i])) / 2; double tem_sin = Math.Sin(T / 180 * halfangle); double tem_cos = Math.Cos(T / 180 * halfangle); int y = Convert.ToInt32(125 * tem_sin); int x = Convert.ToInt32(125 * tem_cos); g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 + x, 225 + y)); g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 + x, 225 + y + 12)); } else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 == 90) { g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225, 225 + 125)); g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225, 225 + 125 + 12)); } else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 > 90 && tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 < 180) { halfangle = (180 - tem_angle - Convert.ToSingle(arraylist_angle[i]) / 2); double tem_sin = Math.Sin(T / 180 * halfangle); double tem_cos = Math.Cos(T / 180 * halfangle); int y = Convert.ToInt32(125 * tem_sin); int x = Convert.ToInt32(125 * tem_cos); g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 - x, 225 + y)); g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 - x, 225 + y + 12)); } else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 == 180) { g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 - 125, 225)); g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 - 125, 225 + 12)); } else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 > 180 && tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 < 270) { halfangle = (tem_angle - 180 + Convert.ToSingle(arraylist_angle[i]) / 2); double tem_sin = Math.Sin(T / 180 * halfangle); double tem_cos = Math.Cos(T / 180 * halfangle); int y = Convert.ToInt32(125 * tem_sin); int x = Convert.ToInt32(125 * tem_cos); g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 - x, 225 - y)); g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 - x, 225 - y + 12)); } else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 == 270) { g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225, 225 - 125)); g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225, 225 - 125 + 12)); } else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 > 270 && tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 < 360) { halfangle = (360 - tem_angle - Convert.ToSingle(arraylist_angle[i]) / 2); double tem_sin = Math.Sin(T / 180 * halfangle); double tem_cos = Math.Cos(T / 180 * halfangle); int y = Convert.ToInt32(125 * tem_sin); int x = Convert.ToInt32(125 * tem_cos); g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 + x, 225 - y)); g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 + x, 225 - y + 12)); } else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 == 360) { g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 + 125, 225)); g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 + 125, 225 + 12)); } } }
/*需要在界面上拉一個PictureBox控件*/ pictureBox1.Image = bitmap; }
/*動態取色的函數*/ private Color Get_Color(int itemindex) { Color objColor = new Color(); int remainder = itemindex % 5; switch (remainder) { case 0: objColor = Color.FromArgb(57, 134, 155); break; case 1: objColor = Color.FromArgb(70,161,185); break; case 2: objColor = Color.FromArgb(124,187,207); break; case 3: objColor = Color.FromArgb(181,212,224); break; case 4: objColor = Color.FromArgb(200,230,245); break; default: objColor = Color.Yellow; break; } return objColor; }