Article Options
Premium Sponsor
Premium Sponsor

 »  Home  »  .NET Newbie  »  GDI+ Chart Success Part 6: Dynamic Line Chart  »  Basic Chart
 »  Home  »  Windows Development  »  Graphics  »  GDI+ Chart Success Part 6: Dynamic Line Chart  »  Basic Chart
 »  Home  »  Windows Development  »  Win Forms  »  GDI+ Chart Success Part 6: Dynamic Line Chart  »  Basic Chart
GDI+ Chart Success Part 6: Dynamic Line Chart
by Ged Mead | Published  08/22/2006 | .NET Newbie Graphics Win Forms | Rating:
Basic Chart

Drawing the Chart Guidelines
The next step is to draw the horizontal guidelines on the chart. These are drawn as soon as the form is first loaded and (as you will see shortly) are redrawn each time the chart is updated with new values.

In this first example, we will use hard coded values in the procedure that draws the guidelines. This is only because it makes the code simpler and the explanations shorter. Later in the article we will use a more flexible, modular and more realistic approach .

In the Code Window for the form, add the following procedure:

Private Sub DrawGuidelines(ByVal PicBox As PictureBox)
' Create a bitmap to draw on and grab its Graphics Object
Dim bmp As New Bitmap(PicBox.Width, PicBox.Height)
Dim gr As Graphics = Graphics.FromImage(bmp)

' Draw guidelines on this graphics object .
For i As Integer = 40 To 400 Step 40
gr.DrawLine(Pens.WhiteSmoke, 0, i, PicBox.Width, i)
Next i

' Assign the bitmap back to the PictureBox as its Image.
PicBox.Image = bmp
End Sub

How It Works
 Let's analyse what this code actually does. (If you have read the previous articles this will be familiar to you, but if you have jumped in here at Part 6 some explanation of what is going on will be useful, I'm sure).

The first two lines of code in the procedure:

Dim bmp As New Bitmap(PicBox.Width, PicBox.Height)
Dim gr As Graphics = Graphics.FromImage(bmp)

can be broken down as follows:

  1. Dim bmp As New Bitmap: Creates a Bitmap object.
  2. (PicBox.Width, PicBox.Height): Sets the size of this Bitmap to be the same size as the PictureBox on which we will draw the graph.
  3. Dim gr As Graphics: Creates a Graphics Object.
    (A Graphics object can be thought of as a kind of "canvas" that is laid over a control and onto which lines and shapes can be drawn).
  4. = Graphics.FromImage(bmp): Specifically assign the Graphics object from the Bitmap that we have just created. We will draw the lines on this Graphics object

We've made a start. Let's check it out.
In the Form's Load event insert the following code which will call the above procedure and draw ten evenly spaced lines across the PictureBox:

Private Sub _1stDemo_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
' Draw horizontal lines on the picturebox
DrawGuidelines(Me.picGraph)
End Sub

Try It Out


Try out the code so far. You should see something like this:


Guidelines



Charting the Values
The next part of the code is the key to the dynamism of the chart. Whenever the user changes the recorded value by scrolling the ScrollBar, here's what we will do:

  1. Take a 'snapshot' of the previous display by grabbing the current image from the PictureBox in which we are creating the chart.
  2. Extend the guidelines at the right hand side of the drawing. (You'll see why in a minute).
  3. 'Paste' the snapshot of the previous display back on to the Bitmap's Graphics Object, BUT place it slightly to the left so that some of this snapshot falls outside the viewable area of the PictureBox.
    (There would an empty gap at the right hand side now if we hadn't extended the guidelines in the last step).
  4. Calculate the point on the Y (vertical axis) where the currently selected value should be marked.
    Note that we have to scale this to make full use of the available height of the PictureBox. In our current example, where we have carefully set the PictureBox height to 400 and the ScrollBar maximum to 100, we therefore have a scale of 4:1 (that is, each increment of 1 in the ScrollBar value is represented by 4 vertical pixels in the PictureBox.)
  5. Move the start point from the default position at the Top Left of the PictureBox, so that the drawing will now start at the Bottom Left corner of the PictureBox.
    The key thing to understand is that when you draw lines in a PictureBox, the point of origin - the Point with values (0,0)- is always in the top left hand corner.
    Then, when you draw a line from that point - to Point (50, 100) for example - then the pen will move 50 pixels across and 100 pixels down.
    This is fine for most drawing tasks, but in a chart we expect the line to move upwards as values increase, not downwards. Therefore we want our chart line to begin in the bottom left corner to represent a value of zero (Point 0,0) and increasing values to be represented by an upward moving line.
  6. Draw the next line segment. This line will extend from the point where the last value plotted ended to the point required to represent the current value.
    Remembering what was said above about lines being drawn from top to bottom, we also have to flip the line so that it becomes drawn from bottom to top (otherwise it would be drawn in an area out of view).
    In this example, this is achieved very simply by plotting the negative equivalents of the values.
  7. All the drawing tasks for the latest value are now complete, so we can assign our freshly redrawn bitmap as the Image property of the PictureBox.
    This will update the display and the user will see the results of our actions above.
  8. Finally, good housekeeping - we dispose of the Graphics object as we have finished with it for this cycle of actions.

The following code will do the job:-

We need to set up a few variables. The first one will represent the length of each segment of the graph - that is, the number of pixels used horizontally on the screen as each new part of the graph is added. Add the code below to the top of the form:

Dim Xmove As Integer = 3

Because we are going to be drawing the graph of an ever changing set of values, we will need to be able to refer to the last used value as well as the current one. The two variables shown below will be used for this task:

Private OldValue As Single = 0
Private NewValue As Single = 0
Now for the actual procedure which produces the goods. It is named DrawGuidelinesAndChart:
Private Sub DrawGuidelinesAndChart(ByVal PicBox As PictureBox)
' Step 1
' Grab the current image (the latest version of the chart)

Dim bm As New Bitmap(PicBox.Width, PicBox.Height)
Dim gr As Graphics = Graphics.FromImage(bm)
' Step 2
' Tack missing guidelines to right hand side on the Graphics object.

For i As Integer = 40 To 400 Step 40
gr.DrawLine(Pens.WhiteSmoke, PicBox.Width - Xmove, i, PicBox.Width, i)
Next i


' Step 3
' Draw this grabbed image, placing it Xmove pixels to the left of the
' image area. (that is, the first few pixels will be invisible because
' they are now outside the picturebox's viewable area)
gr.DrawImage(PicBox.Image, -Xmove, 0)
' Note that we are still drawing on the Graphics object.
' No change will appear on the PictureBox yet.

' Step 4
' Plot the new value. That is, calculate where on the Y axis (the
' vertical plane) this new value should be marked.
' This calculation takes into account the scale of the min/max values
' range in relation to the total height of the PictureBox.
' In this example this is 4:1 (PictureBox Height is 400:Max value on the ScrollBar is 100)
' so we multiply the selected value by a scale of 4
NewValue = SBUserValue.Value * 4
' Step 5
' Shift start point from top left to bottom left.
gr.TranslateTransform(0, picGraph.Height)
' Step 6
' Draw the next line segment on the Graphics object.
' Note that the NEGATIVE values of OldValue and NewValue
' are used for the Y positions.
' This will reverse the position of those points and make them
' appear in the PictureBox. If you don't do this, they will be
' drawn down below the bottom of the PictureBox and therefore
' out of view of the user.

gr.DrawLine(Pens.Black, _
picGraph.Width - 1 - Xmove, -OldValue, _
picGraph.Width - 1, -NewValue)
OldValue = NewValue

' Step 7
' Display the results by assigning this edited Bitmap as the
' Image of the PictureBox.
picGraph.Image = bm
' Step 8
' All done

gr.Dispose()
' For confirmation purposes, display the currently selected value in a label
lblValue.Text = SBUserValue.Value.ToString
End Sub

Using the Vertical ScrollBar
As mentioned earlier, the vertical ScrollBar used in this demonstration is just an easy way to generate a set of fast-changing values to show on the graph. What we need to do now is write some code that kicks in each time the value of the ScrollBar is changed by the user.
The place to do this in the ScrollBar's ValueChanged event.

Private Sub SBUserValue_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles SBUserValue.ValueChanged
DrawGuidelinesAndChart(picGraph)
End Sub

Test It

Now run the project and move the ScrollBar. Each movement of the ScrollBar should result in a new value being plotted on the chart. You can check what value was last selected by viewing the value shown in the label.
As you'll see, the Vertical ScrollBar creates higher values as it is moved downwards; lower values as it is moved upwards. If you find this confusing, you can easily replace the Vertical ScrollBar with a Horizontal one. In that case, lower values are selected as you scroll to the left and higher values to the right, which you may think is more logical.

 

First Demonstration Summary
With relatively little code, we have created a useful dynamic line chart. You can replace the ScrollBar that I have used with any other means of taking values that would be relevant for your projects, whether this be user input, system produced information, external data, time based data, and so on.

Of course, you can't always guarantee that the values used will fall neatly into the 1 to 100 range we used for this first example, so we will shortly look at how we can edit the code to make it more flexible.
First though, I want to look at a couple of ways of producing some interesting alternative displays.

Sponsored Links