Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

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?

Posted

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

Posted

Got it

used:

bm.Save(Application.LocalUserAppDataPath + "/chart.png", ImageFormat.Png);
		 this.Final = Image.FromFile(Application.LocalUserAppDataPath + "/chart.png");

  • Leaders
Posted

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;

[sIGPIC]e[/sIGPIC]
Posted

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..

  • Leaders
Posted
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.
[sIGPIC]e[/sIGPIC]
Posted

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;

  • Leaders
Posted

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.

[sIGPIC]e[/sIGPIC]

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...