Newsletter sign-up
View all newsletters

Sign up for our technology specific newsletters.

Enterprise Java
Email Address:

Chart your way to custom graph components

Learn to build a graph framework and custom graph components

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone

Page 3 of 4

We'll draw the rectangles in the color specified by the GraphItem. To allow us to go back to the original color, we set a temporary color variable to hold the current value before we change it. We cycle through the vector of graph items, calculating an adjusted vertical value for each one, drawing the title of the item and a filled rectangle representing its value. The increment is added to the x position variable each time through the loop.

The adjusted vertical value ensures that if the component is stretched vertically, the graph will still remain true to its plotted values. To do this properly, we need to take the percentage of the range the item represents and multiply that value by the actual pixel range of the graph drawing region. We then subtract the result from the bottom value to correctly plot the point.

As you can see from the following diagram, the total horizontal pixel size is represented by right - left and the total vertical size is represented by bottom - top.


Adjusted vertical and horizontal values

We take care of the horizontal stretching by initializing the position variable to the left edge and increasing it by the increment variable for each item. Because the position and increment variables are dependent on the actual current pixel values, the component is always resized correctly in the horizontal direction.

To ensure that the vertical plotting is always correct, we must map the graph item values with actual pixel placements. There is one complication: The max and min values should be meaningful to the position of the graph item value. In other words, if the graph starts at 150 and goes to 200, an item with a value of 175 should appear halfway up the vertical axis. To achieve this, we find the percentage of the graph range that the item represents and multiply it by the actual pixel range. Because our graph is upside down from the graphics context's coordinate system, we subtract this number from bottom to find the correct plot point. Remember, the origin (0,0) is in the upper-left corner for the code, but the bottom-left corner for the style of graph we are creating.

Building the line graph

The bar chart was just a warm up. Now we're ready to tackle a slightly more complicated type of graph -- a line graph, which is shown in the following figure. The technique we're going to use is the same as with the bar chart, but we'll be required to do more counting and measuring.


A typical line graph
import java.awt.*;
   public class LineGraph extends Graph {
      int increment;
      int position;
   public LineGraph(String title, int min, int max) {
      super(title, min, max);
   }


Just as before, we need to space the items evenly, so we keep an increment variable to indicate the amount we will shift to the right for each item. The position variable is the current position, and the increment variable is added to it each time. The constructor simply calls the super constructor.

Almost all of the work is done in the paint method. Let's look at that now.

   public void paint(Graphics g) {
      super.paint(g);
      increment = (right - left)/(items.size() - 1);
      position = left;
      Color temp = g.getColor();
      GraphItem firstItem = (GraphItem)items.firstElement();
      int firstAdjustedValue = bottom - (((firstItem.value - min)*(bottom - top)
                                         )/(max - min));
      g.setColor(firstItem.color);
      g.drawString(firstItem.title, position - fm.stringWidth(firstItem.title),
                   firstAdjustedValue - 2);
      g.fillOval(position - 2, firstAdjustedValue - 2, 4, 4);
      g.setColor(temp);
      for (int i = 0; i < items.size() - 1; i++) {
         GraphItem thisItem = (GraphItem)items.elementAt(i);
         int thisAdjustedValue = bottom - (((thisItem.value - min)*
                                 (bottom - top))/(max - min));
         GraphItem nextItem = (GraphItem)items.elementAt(i+1);
         int nextAdjustedValue = bottom - (((nextItem.value - min)*
                                 (bottom - top))/(max - min));
         g.drawLine(position, thisAdjustedValue,
                    position+=increment, nextAdjustedValue);
         g.setColor(nextItem.color);
         if (nextAdjustedValue < thisAdjustedValue)
            g.drawString(nextItem.title, position - fm.stringWidth(nextItem.title),
                         nextAdjustedValue + titleHeight + 4);
         else
            g.drawString(nextItem.title, position - fm.stringWidth(nextItem.title),
                         nextAdjustedValue - 4);
         g.fillOval(position - 2, nextAdjustedValue - 2, 4, 4);
         g.setColor(temp);
      }
   } // end paint


We first call the super paint method to draw the framework, then we implement our custom graph drawing. We find the value of the increment by measuring the difference between the left and right edges of the graph region and then by dividing the result by the number of elements minus 1. This formula will produce the correct increment value. Because we are drawing points with the first one at the left edge and the last one at the right edge, the increment is slightly different than it was with the bar chart. The position is initialized to the left edge of the drawing area.

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comments (2)
Login
Forgot your account info?

Yes, it does work!By Anonymous on March 26, 2009, 11:20 amThe author may take this lesson out of context and assume that you can wrap his work with a simple JFrame yourself, but indeed it does work just fine. www.GoMotocross.com

Reply | Read entire comment

graph framework and custom graph componentsBy danjospehj82 on March 11, 2009, 9:49 pmDoes this code actually work I wonder??

Reply | Read entire comment

View all comments

Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources
  • Previous Step by Step articles