Title: Draw a simple histogram in C#
When the program loads, the following code generates some random data.
private const int MIN_VALUE = 0;
private const int MAX_VALUE = 100;
private float[] DataValues = new float[10];
// Make some random data.
private void Form1_Load(object sender, EventArgs e)
{
Random rnd = new Random();
// Create data.
for (int i = 0; i < DataValues.Length; i++)
DataValues[i] = rnd.Next(MIN_VALUE + 5, MAX_VALUE - 5);
}
This code creates a new Random object and uses it to fill the DataValues array with random values.
The form's Paint event handler calls the DrawHistogram method, which does all of the interesting work.
// Draw the histogram.
private void picHisto_Paint(object sender, PaintEventArgs e)
{
DrawHistogram(e.Graphics, picHisto.BackColor, DataValues,
picHisto.ClientSize.Width, picHisto.ClientSize.Height);
}
When the program's PictureBox resizes, its Resize event handler refreshes it, making the Paint event handler run again.
// Redraw.
private void picHisto_Resize(object sender, EventArgs e)
{
picHisto.Refresh();
}
The following code shows the DrawHistogram method.
// Draw a histogram.
private void DrawHistogram(Graphics gr, Color back_color,
float[] values, int width, int height)
{
Color[] Colors = new Color[] {
Color.Red, Color.LightGreen, Color.Blue,
Color.Pink, Color.Green, Color.LightBlue,
Color.Orange, Color.Yellow, Color.Purple
};
gr.Clear(back_color);
// Make a transformation to the PictureBox.
RectangleF data_bounds =
new RectangleF(0, 0, values.Length, MAX_VALUE);
PointF[] points =
{
new PointF(0, height),
new PointF(width, height),
new PointF(0, 0)
};
Matrix transformation = new Matrix(data_bounds, points);
gr.Transform = transformation;
// Draw the histogram.
using (Pen thin_pen = new Pen(Color.Black, 0))
{
for (int i = 0; i < values.Length; i++)
{
RectangleF rect = new RectangleF(i, 0, 1, values[i]);
using (Brush the_brush =
new SolidBrush(Colors[i % Colors.Length]))
{
gr.FillRectangle(the_brush, rect);
gr.DrawRectangle(thin_pen, rect.X, rect.Y,
rect.Width, rect.Height);
}
}
}
gr.ResetTransform();
gr.DrawRectangle(Pens.Black, 0, 0, width - 1, height - 1);
}
This code applies a transformation to the Graphics object to map the histogram's coordinates so they fill the PictureBox. It then loops through the data values drawing their histogram bars. It makes the transformation map the number of data values to the PictureBox's width so it can draw each bar with a width of 1 in value coordinates.
Note that the code uses a pen of width 0 to outline the bars. A pen of width 0 is always drawn 1 pixel wide no matter what transformation is in use. (Try using a pen of width 1 and see what happens.)
When the user clicks on the graph, the program uses the following code to determine which histogram bar is under the mouse and displays the corresponding data value.
// Display the value clicked.
private void picHisto_MouseDown(object sender, MouseEventArgs e)
{
// Determine which data value was clicked.
float bar_wid = picHisto.ClientSize.Width /
(int)DataValues.Length;
int i = (int)(e.X / bar_wid);
MessageBox.Show("Item " + i + " has value " + DataValues[i],
"Value", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
Download the example to experiment with it and to see additional details.
|