MrLucky Posted March 5, 2006 Posted March 5, 2006 I have a program, that can create a chart with System.Drawing. Is it possible when the chart is created, the chart is the image for a Picture box? So when the chart is created, it will direchtly shown in a picture box. Is that possible? Quote
Leaders snarfblam Posted March 5, 2006 Leaders Posted March 5, 2006 Are you drawing the chart? Or are you using a third party library? Is the output in the form of an in-memory bitmap? A .bmp file? Quote [sIGPIC]e[/sIGPIC]
MrLucky Posted March 5, 2006 Author Posted March 5, 2006 I use this class: using System; using System.IO; using System.Data; using System.Drawing; using System.Drawing.Text; using System.Drawing.Drawing2D; using System.Drawing.Imaging; namespace RM { public class PieChart { private int[] values; private string[] legends; public System.Drawing.Image Final; public PieChart() { } public void SetValues(int[] values) { this.values = values; } public void SetLegends(string[] legends) { this.legends = legends; } public void Render(string title, string subTitle, int width, int height) { const int SIDE_LENGTH = 400; const int PIE_DIAMETER = 200; //calculate total amount of units in the pie, based on the data passed in float sumData = 0; foreach(int value in this.values) { sumData += Convert.ToSingle(value); } //create a new image Bitmap bm = new Bitmap(width,height); Graphics g = Graphics.FromImage(bm); //set image attributes g.ScaleTransform((Convert.ToSingle(width))/SIDE_LENGTH,(Convert.ToSingle(height))/SIDE_LENGTH); g.SmoothingMode = SmoothingMode.HighQuality; g.TextRenderingHint = TextRenderingHint.AntiAlias; //draw canvas and border g.Clear(Color.White); g.DrawRectangle(Pens.Black,0,0,SIDE_LENGTH-1,SIDE_LENGTH-1); //draw title g.DrawString(title,new Font("Tahoma",14),Brushes.Black,new PointF(5,5)); //draw sub-title g.DrawString(subTitle,new Font("Tahoma",10),Brushes.Black,new PointF(7,35)); //draw the pie float curAngle = 0; float totalAngle = 0; for(int i=0; i < this.values.Length; i++) { curAngle = Convert.ToSingle(this.values[i]) / sumData * 360; g.FillPie(new SolidBrush(ChartUtil.GetChartItemColor(i)),100,65,PIE_DIAMETER,PIE_DIAMETER, totalAngle, curAngle); g.DrawPie(Pens.Black,100,65,PIE_DIAMETER,PIE_DIAMETER,totalAngle,curAngle); totalAngle += curAngle; } //draw legend box and label g.DrawRectangle(Pens.Black,200,300,199,99); g.DrawString("Legend",new Font("Tahoma",10,FontStyle.Bold),Brushes.Black,new PointF(200,300)); //draw legend items PointF boxOrigin = new PointF(210,330); PointF textOrigin = new PointF(235,326); float percent = 0; for(int i=0; i < this.legends.Length; i++) { g.FillRectangle(new SolidBrush(ChartUtil.GetChartItemColor(i)),boxOrigin.X,boxOrigin.Y,20,10); g.DrawRectangle(Pens.Black,boxOrigin.X,boxOrigin.Y,20,10); percent = Convert.ToSingle(this.values[i]) / sumData * 100; g.DrawString(this.legends[i] + " - " + this.values[i] + " (" + percent.ToString("0") + "%)",new Font("Tahoma",10),Brushes.Black,textOrigin); boxOrigin.Y += 15; textOrigin.Y += 15; } this.Final = bm; //garbage collection bm.Dispose(); g.Dispose(); } } } I want the image created with that, in my picture box Quote
MrLucky Posted March 5, 2006 Author Posted March 5, 2006 Got it used: bm.Save(Application.LocalUserAppDataPath + "/chart.png", ImageFormat.Png); this.Final = Image.FromFile(Application.LocalUserAppDataPath + "/chart.png"); Quote
Leaders snarfblam Posted March 5, 2006 Leaders Posted March 5, 2006 I don't understand how that helps. Are you trying to save the image? Or show it in a PictureBox? To put it in a picture box, you don't need to save it. Just Do something like this: SomePictureBox.Image = SomePieChartObject.Final; Quote [sIGPIC]e[/sIGPIC]
MrLucky Posted March 5, 2006 Author Posted March 5, 2006 When I tried that, I got an error saying it was not the right type. My chart was a System.Drawing.Bitmap and a picturebox needs a System.Drawing.Image.. Quote
Leaders snarfblam Posted March 5, 2006 Leaders Posted March 5, 2006 System.Drawing.Bitmap is a System.Drawing.Image. Bitmap and Metafile both inherit from the Image property. Anything that asks for an Image will accept a Bitmap or Metafile. Perhaps you should post the code where this exception is being thrown. Quote [sIGPIC]e[/sIGPIC]
MrLucky Posted March 5, 2006 Author Posted March 5, 2006 Ok without saving, I use this function: public Bitmap Render(string title, string subTitle, int width, int height) { const int SIDE_LENGTH = 400; const int PIE_DIAMETER = 150; const float PIE_X = 100; const float PIE_Y = 65; //calculate total amount of units in the pie, based on the data passed in float sumData = 0; foreach(int value in this.values) { sumData += Convert.ToSingle(value); } //create a new image Bitmap bm = new Bitmap(width,height); Graphics g = Graphics.FromImage(bm); //set image attributes g.ScaleTransform((Convert.ToSingle(width))/SIDE_LENGTH,(Convert.ToSingle(height))/SIDE_LENGTH); g.SmoothingMode = SmoothingMode.HighQuality; g.TextRenderingHint = TextRenderingHint.AntiAlias; //draw canvas and border g.Clear(Color.White); g.DrawRectangle(Pens.Black,0,0,SIDE_LENGTH-1,SIDE_LENGTH-1); //draw title g.DrawString(title,new Font("Tahoma",16),Brushes.Black,new PointF(5,5)); //draw sub-title g.DrawString(subTitle,new Font("Tahoma",12),Brushes.Black,new PointF(7,35)); //draw the pie float curAngle = 0; float totalAngle = 0; for(int i=0; i < this.values.Length; i++) { curAngle = Convert.ToSingle(this.values[i]) / sumData * 360; g.FillPie(new SolidBrush(this.colors[i]), PIE_X, PIE_Y, PIE_DIAMETER, PIE_DIAMETER, totalAngle, curAngle); g.DrawPie(Pens.Black, PIE_X, PIE_Y,PIE_DIAMETER,PIE_DIAMETER,totalAngle,curAngle); totalAngle += curAngle; } //draw legend box and label g.DrawRectangle(Pens.Black, 10, PIE_Y + PIE_DIAMETER + 5,SIDE_LENGTH - 20,height); g.DrawString("Legend",new Font("Tahoma",10,FontStyle.Bold),Brushes.Black,new PointF(15, PIE_Y + PIE_DIAMETER + 10)); //draw legend items PointF boxOrigin = new PointF(15, PIE_Y + PIE_DIAMETER + 30); PointF textOrigin = new PointF(35,PIE_Y + PIE_DIAMETER + 27); float percent = 0; for(int i=0; i < this.legends.Length; i++) { g.FillRectangle(new SolidBrush(this.colors[i]),boxOrigin.X,boxOrigin.Y,20,10); g.DrawRectangle(Pens.Black,boxOrigin.X,boxOrigin.Y,20,10); percent = Convert.ToSingle(this.values[i]) / sumData * 100; g.DrawString(this.legends[i] + " - " + this.values[i] + " (" + percent.ToString("0") + "%)",new Font("Tahoma",10),Brushes.Black,textOrigin); boxOrigin.Y += 15; textOrigin.Y += 15; } /*string random_string = ChartUtil.RandomString(8, false); FileStream filestream = new FileStream(System.IO.Path.GetTempPath() + "/" + random_string + ".png", FileMode.OpenOrCreate, FileAccess.Write); bm.Save(filestream, ImageFormat.Png); filestream.Close(); this.Final = Image.FromFile(System.IO.Path.GetTempPath() + "/" + random_string + ".png");*/ System.Drawing.Bitmap final = bm; //garbage collection bm.Dispose(); g.Dispose(); return final; } } In my form class: i use this: chart.SetValues(values); chart.SetLegends(legends); chart.SetColors(colors); System.Drawing.Bitmap final = chart.Render("Most played songs", "", 400, 400); // Update our picturebox graphMostPlayed.Image = final; But when I start my program, and click the button, so my chart will be created, i get this error: Parameter is not valid on this line: graphMostPlayed.Image = final; Quote
Leaders snarfblam Posted March 5, 2006 Leaders Posted March 5, 2006 The problem is that you dispose of the bitmap... System.Drawing.Bitmap final = bm; bm.Dispose(); then you try to display it... graphMostPlayed.Image = final; Although you are Disposing() one variable and assigning a different variable to the PictureBox, they both reference the same object. Quote [sIGPIC]e[/sIGPIC]
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.