Home : Course Map : Chapter 6 : Java : Tech :
Starting to Plot
JavaTech
Course Map
Chapter 6

Introduction
AWT
Swing
Containers
  Demo 1
UI Components
  Demo 2
UI Layout
  Demo 3   Demo 4
Text Display
  Demo 5
Drawing
  Demo 6   Demo 7
Draw Polygons
  Demo 8   Demo 9
Colors
Text Draw 
  Demo 10
Images
  Demo 11
Exercises

    Supplements
AWT
  Demo 1
Drawing
  Demo 2
Text Drawing
  Demo 3
UI Components
  Demo 4

Java2D
Shapes & Areas
  Demo 1   Demo 2
Stroke & Paint
  Demo 3
Transforms
  Demo 4
Gradients&Textures
  Demo 5   Demo 6
Text
  Demo 7   Demo 8
     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

In this section we develop the first of a series of classes that will demonstrate object oriented programming and Java graphics techniques. We will use these classes for plotting data and for user interface tasks in our example programs in the rest of the course. Note also that with the exercises you will get the opportunity to enhance and customize these classes.

Some of the considerations in developing our Java plotting classes include:

  • Modularity - we want the classes to easily plug into where they are needed.

  • Flexibility - provide lots of options but with default settings for cases where the basic implementation is sufficient.

  • Relative positioning - as we will see in the Chapter 7 : Java : Layout Managers, positioning and sizing of graphics components in Java are almost always done with relative rather than absolute coordinates. Your programs will run on different sized screens and resolutions, and within variable window sizes. So relative layout provides the most sensible approach.

  • Graphics vs Graphics2D - for these classes we will stay with the basic techniques available from the Graphics context class but in the exercises you can convert the classes to Java2D.

PlotPanel is our first plotting support class. It is an abstract class that provides a frame around our data plots and a title, scale values, and a horizontal axis label. PlotPanel extends JPanel so we will be able to use this class easily in our layouts for display purposes.

PlotPanel includes four methods that a subclass must override. These are the methods that provide the title, the horizontal axis label, the scale numbers on the axes, and the plot inside the frame.

  • abstract String getTitle () - title for the plot

  • abstract String getXLabel () - label for the horizontal axis.

  • abstract void getScaling () - create two floating-point arrays that hold the values to display on the vertical and horizontal axes. The arrays will be instance variables used by the paintContents() method.

  • abstract void paintContents (Graphics g) - draw the "inside" of the plot box, i.e. data points or whatever you wish to display. Invoke the drawAxesNumbers() method (see below) to put the scale values along the x and y axes.

For the axes scale numerical values, we use a static utility method - getFormatted() - in the class PlotFormat to convert double values to strings. You select decimal or scientific format depending on the magnitude of the value.

The PlotPanel code, intended as a support class for various plot programs to come, is fairly long but most of it deals with the details of determining the positioning and sizing of the frame, text, and so forth. Understanding the the nitty-gritty of all this book-keeping is less important that seeing the overall structure of the class.

First of all, there are many data fields in PlotPanel. Most of these are parameters that determine the size and appearance of the plot.

Secondly, the methods include:

  • getPositions () - from the panel frame dimensions, calculate the positions and dimensions of the plot frame, the plot title, the axes scale numbers, etc. The plot goes as a fraction of the panel frame, e.g. the constant FRAME_WD set to 0.60, means that the plot width will be set to 60% of the frame width.

  • paintFrame (Graphics g) - draw the frame of the plot.

  • drawAxesNumbers (Graphics g, double [] x_value, double [] y_value) - draw on the plot axes the data points, whose positions are given by the x_value, y_value arrays. These values would normally be calculated in your overriden version of getScaling().

  • drawText (Graphics g, String msg, int x_box, int y_box, int box_width, int box_height, int fixed_type_size_value, int position) - this utility method draws a string, such as an axis scale number, in the center of a given boxed area. It reduces the font size if necessary to fit inside the box. Alternatively, you can fix the type size to a specific value passed as an argument. The position of the string within the box is passed as LEFT, CENTER or RIGHT constant value. It won't draw the string if it can not make it fit.

  • paintComponent (Graphics g) - after painting the panel's background coloer, this method invokes getPositions () to determine the plot parameters and then it invokes drawText() once to draw the title above the plot and then invokes drawText() again to draw the x axis label. This is followed by invoking paintFrame (g) to draw the lot box. Finally, it invokes paintContents(), which will be the overriden method that draws whatever the subclass intends, typically a data plot of some kind.

The code uses informative names for the variables and methods andprovides lots of comments in an effort to make the program understandable.

DemoPanel extends PlotPanel and overrides the four abstrct methods to draw a set of dummy data points with error bars. The


PlotDemoApplet.java - Demonstrate the use of PlotPanel to plot a set of data points with error bars within a box with scaled axes.

DemoPanel.java - this PlotPanel subclass illustrates how to work with PlotPanel wby plotting a set of dummy data points with error bars.

PlotPanel.java - this subclass of JPanel provides a frame with a title, axes scale values, and a horizontal label within which a subclass can plot the data of interest. We will use it as our base class in subsequent subclasses on which to draw histograms, plots, and animations upon.

PlotFormat.java
- utility class that uses the DecimalFormat methods to format the scale numbers placed along the plot axes.

Java Techniques & Other Programming Notes

  • The abstract PlotPanel does all the "grunt work" involved in setting up the box, or frame as it's called in the class, with the x-y axes, the scale values along the x-y axes, title on top, and a label along the x axis. This allows for the subclasses to concentrate just on the particular plotting tasks they need to do.

  • The PlotPanel class properties include a number of variables for the display settings such as the colors of the frame and so forth. More getter/setter methods could be added to allow for other classes to access and modify these variables.

  • The PlotPanel class provides for basic plot capabilities and could be greatly expanded. The student, in fact, would do well to start from scratch and develop his/her own plotting classes.

  • PlotFormat illustrates how to use static methods to provide useful services and provides an exercise in using the number format tools. It could be upgraded to use the newer Formatter class tools.

import javax.swing.*;
import java.awt.*;

/** Demonstrate the plotting classes. **/
public class
PlotDemoApplet extends JApplet
{
  public void init () {
    Container content_pane = getContentPane();

    // Create an instance of a JPanel sub-class DemoPanel
    DemoHist demo_panel = new DemoPanel ();

    // And add one or more panels to the JApplet panel.
    content_pane.add (hist_panel);
  }
// init
} // class PlotDemoApplet

import java.awt.*;
import javax.swing.*;

/**
  * Display a set of dummy data to demonstrate
  * plotting techniques. Extend PlotPanel and
  * override the abstract methods:
  *
  *   getScaling() gets the scales for the x & y axes.
  *   paintContents() to draws a set of data points.
  *   getTitle() provides the title above the frame.
  *   getXLabel() provides label for bottom horizontal axis.
  *
 **/
public class DemoPanel extends PlotPanel
{
  // Arrays to hold data points and their error bar values.
  double [] fDataY;
  double [] fDataX;
  double [] fErrY;
  double [] fErrX;

  // Upper limits of the data.
  double fYDataMax = 1000.0;
  double fXDataMax = 100.0;

  // Lower range of the data.
  double fYDataMin = 0.0;
  double fXDataMin = 0.0;

  // Numbers to use for plotting axes scale values
  double [] fXScaleValue;
  double [] fYScaleValue;
  int fNumYScaleValues = 5;
  int fNumXScaleValues = 5;

  /**
    * The constructor creates the dummy data.
   **/
  public DemoPanel () {
    // Create some dummy data
    double []tmp_y   =  { 51.1, 154.5, 249.2, 401.3, 731.3, 870.2};
    double []tmp_y_err= { 28.3,  49.0,  75.8, 100.4, 150.2, 200.0};

    double []tmp_x   =  {  4.3,  13.4,  33.1,  54.8,  71.3,  88.5};
    double []tmp_x_err= {  3.0,   3.0,   3.0,   3.0,   4.0,   5.0};

    fDataY = tmp_y;
    fDataX = tmp_x;
    fErrY  = tmp_y_err;
    fErrX  = tmp_x_err;

    getScaling ();
  } // ctor

  /**
    * Create the arrays with the values for the scaling numbers
    * to plot along the vertical and horizontal axes.
   **/
  void getScaling () {

    // The vertical scale array
    fYScaleValue = new double[fNumYScaleValues];

    // Set the lower and upper limits for the y scale value;
    fYScaleValue[0] = fYDataMin;
    fYScaleValue[fNumYScaleValues-1] = fYDataMax;

    // Then calculate the difference between the values
    double range = fYScaleValue[fNumYScaleValues-1]
                        - fYScaleValue[0];
    double del = range/(fNumYScaleValues-1);

    // Now fill the array with the scale values.
    for (int i=1; i < (fNumYScaleValues-1); i++) {
        fYScaleValue[i] = i * del + fYScaleValue[0];
    }


    // The horizontal scale array
    fXScaleValue = new double[fNumXScaleValues];

    // Set the lower and upper limits for the x scale value;
    fXScaleValue[0] = 0.0;
    fXScaleValue[fNumXScaleValues-1] = fXDataMax;

    // Then calculate the difference between the values
    range = fXScaleValue[fNumXScaleValues-1]
                        - fXScaleValue[0];
    del = range/(fNumXScaleValues-1);

    // Now fill the array with the scale values.
    for (int i=1; i <  (fNumXScaleValues-1); i++) {
        fXScaleValue[i] = i * del + fXScaleValue[0];
    }

  } // getScaling


  /**
    * Override paintContents() to draw the plot inside the frame.
    * From the data arrays draw a different symbol for each data
    * data point and also draw x, y error bars.
    *
   **/
  void paintContents (Graphics g) {

    // Need conversion factor from data scale to pixel scale
    double yConvert = fFrameHeight/fYDataMax;
    double xConvert = fFrameWidth/fXDataMax;

    // For data symbols get size relative to the frame.
    int sym_dim =  (int)(fFrameWidth * 0.01);

    // Create a diamond symbol with a Polygon object.
    // Create diamond over origin and use translate to
    // move it when needed.
    int [] xp = new int[4];
    int [] yp = new int[4];
    xp[0] = sym_dim; xp[2] = -sym_dim;
    xp[1] = xp[3] = 0;
    yp[1] = sym_dim; yp[3] = -sym_dim;
    yp[0] = yp[2] = 0;
    Polygon diamond = new Polygon (xp,yp,4);
    int x_old = 0,y_old = 0;

    // Now loop through the data arrays and draw each point with
    // a different symbol. ALso draw x and y aerror bars.
    for (int i=0; i < fDataY.length; i++) {
        int x_bar = (int)(fErrX[i] * xConvert/2.0);
        int y_bar = (int)(fErrY[i] * yConvert/2.0);
        int x =  (int)(fDataX[i]*xConvert) + fFrameX;
        int y = fFrameHeight - (int)(fDataY[i] * yConvert) + fFrameY;

        // Draw data point symbols
        g.setColor (Color.RED);
        if (i == 0) {
            g.drawRect (x-sym_dim, y-sym_dim, 2*sym_dim,   2*sym_dim);
        }
        else if (i == 1) {
            g.fillRect (x-sym_dim, y-sym_dim, 2*sym_dim+1, 2*sym_dim+1);
        }
        else if (i == 2)
            g.drawOval (x-sym_dim, y-sym_dim, 2*sym_dim,   2*sym_dim);
        else if (i == 3)
            g.fillOval (x-sym_dim, y-sym_dim, 2*sym_dim+1, 2*sym_dim+1);
        else if (i == 4) {
            diamond.translate (x, y);
            g.drawPolygon (diamond);
            x_old = x; y_old = y;
        } else if (i == 5) {
            diamond.translate (x-x_old, y-y_old);
            g.fillPolygon (diamond);
        }

        g.setColor (Color.BLUE);

        // Draw y error bar
        g.drawLine (x, y-y_bar, x, y+y_bar);

        // Draw x error bar
        g.drawLine (x-x_bar, y, x+x_bar, y);
    }

    // Draw the numbers along the axes
    drawAxesNumbers ( g, fXScaleValue, fYScaleValue);

  } // paintContents

  /**
    * Return the title at the top of the plot.
    * Overrides method in PlotPanel.
   **/
  String getTitle ()
  {  return "Plotting Demo"; }

  /**
    * Return the label on the horizontal axis.
    * Overrides method in PlotPanel.
   **/
  String getXLabel ()
  {  return "Y vs X"; }

} // class DemoPanel

import java.awt.*;
import javax.swing.*;

/**
  *  This abstract class extends JPanel and provides methods
  *  to display a plot of data points, a histogram, etc. The
  *  subclass will provide the overriding methods to draw the
  *  actual plot within a frame.
  *
  *  For this class, the words
  *    frame, title, label, scale  
  *  are used in variable and method names, and comments and are
  *  defined as follows:
  *
  *  frame  - The border line box drawn around the plot.
  *  title  - A text title drawn along the top of the frame.
  *  label  - Text along the horizontal axis of the plot.
  *  scale  - The numbers drawn along each axes.
  *
  *  This class only provides for the display of scales along the
  *  left side vertical and bottom horizontal axes. A label is
  *  provided for the bottom horizontal axis but not for the
  *  vertical axis.
  *
  *  The size and position of the frame, title, etc. within
  *  the panel is fixed by a group of constants, each of which
  *  specifies what fraction of the panel's dimensions a given element
  *  can use.
  *
  *  Note that in the comments, "data" refers to what is being
  *  plotted and "pixels" refers to the drawing coordinates and
  *  dimensions.
  *
 **/
public abstract class PlotPanel extends JPanel {

  // Abstract methods for the subclass to override.

  // Provide a title for the top of the frame
  abstract String getTitle ();
  // Provide a label for the bottom horizontal axis.
  abstract String getXLabel ();
  // Create arrays of scale values to plot along the axes.
  abstract void getScaling ();
  // Draw within the the frame the actual plot of interest.
  abstract void paintContents (Graphics g);

  // Variables and constants.

  // Colors for the plot components.
  protected Color fFrameLineColor  = Color.BLACK;
  protected Color fFrameFillColor  = Color.LIGHT_GRAY;
  protected Color fAxesNumColor    = Color.GRAY;
  protected Color fTitleColor      = Color.BLACK;
  protected Color fBgColor         = Color.WHITE;

  // Dimension and position variables in pixel values. (Note that
  // position is indicated by the top corner x,y coords.)
  protected int fPanelWidth, fPanelHeight; // Panel size
  protected int fFrameWidth, fFrameHeight; // Frame size
  protected int fFrameX,fFrameY;           // Frame position
  protected int fTitleX,fTitleY;           // Title position
  protected int fTitleWidth,fTitleHeight;  // Title size

  // Position and size of the area where the vertical scale
  // numbers will be drawn in pixel values.
  protected int fVertScaleX,fVertScaleY,
                fVertScaleWidth,fVertScaleHeight;

  // Position and size of the area where the horizontal scale
  // numbers will be drawn in pixel values.
  protected int fHorzScaleX, fHorzScaleY,
                fHorzScaleWidth,fHorzScaleHeight;

  // Position and size of the area where the horzontal label
  // will be drawn in pixel values.
  protected int fHorzLabelX,fHorzLabelY,
                fHorzLabelWidth,fHorzLabelHeight;


  // Upper limits: if the data values are below these limits then
  // the x, y scale values are put in decimal format. If the data
  // values are above these limits, then the values are put into
  // scientific format.
  double fYDecimalSci = 100.0;
  double fXDecimalSci = 1000.0;

  // Lower limits: if the data values are above these limits then
  // the x, y scale values are put in decimal format. If the data
  // values are below these limits, then the values are put into
  // scientific format.
  double fYLoDecimalSci = 0.01;
  double fXLoDecimalSci = 0.01;

  // The drawText() method first defines a rectangle for the area
  // in which it will draw the given text. The following constants
  // indicate how to align the text within the rectangle.
  final static int CENTER = 0;
  final static int LEFT   = 1;
  final static int RIGHT  = 2;

  // The following constants determine the sizes of the plot
  // elements relative to the panel. These are used in the
  // method getPositions().

  // Fraction of panel for the plot frame
  final static double FRAME_HT = 0.60;// 60% of panel height for frame
  final static double FRAME_WD = 0.75;// 75% of window width for frame
  final static double FRAME_X  = 0.20;// put top left corner at 20% of width
  final static double FRAME_Y  = 0.15;// put top left corner at 15% of height

  // Fraction of vertical area for the title
  protected double TITLE_HT = 0.10;

  // Fractions of the panel for left scale values
  final static double VSCALE_X = 0.100;
  final static double VSCALE_HT= 0.075;
  final static double VSCALE_WD= 0.18;

  // Fraction of vertical for the horizontal scale values
  protected double HSCALE_HT= 0.07;

  /**
    * Determine the positions of the title, label and scales
    * relative to the frame.
    *
    * Use 60% of vertical space for the graph,
    *  "  15%  "    "      "     "  top title area
    *  "  25%  "    "      "     "  bot scale & label area
    * Use 75% of horizonal space for the graph,
    *   " 18%  "    "      "     "   vertical scale values
    *   "  5%  "    "      "     "   right margin
    *
   **/
  public void getPositions () {
    // First obtain the panel dimensions
    fPanelWidth  = getSize ().width;
    fPanelHeight = getSize ().height;

    // Then assign the frame dimensions.
    fFrameWidth =  (int) (FRAME_WD * fPanelWidth);
    fFrameHeight=  (int) (FRAME_HT * fPanelHeight);

    // Locate the frame by assigning its top left corner coords.
    fFrameX =  (int)(FRAME_X * fPanelWidth);
    fFrameY =  (int)(FRAME_Y * fPanelHeight);

    // Coordinates for the title
    fTitleX = fFrameX ;
    fTitleHeight =  (int)(TITLE_HT * fPanelHeight);
    fTitleY = fFrameY - fTitleHeight;
    fTitleWidth = fFrameWidth;

    // Coordinates for the vertical scale along the left
    // side axis.

    // Use all the horizontal room from the left side
    // up to the left edge of the frame.
    fVertScaleX      = 0; // Left most position
    // Use the VSCALE_WD fraction of the panel's width.
    fVertScaleWidth  = (int)(VSCALE_WD * fPanelWidth);
    // Use the VSCALE_HT fraction of the panel's height.
    fVertScaleHeight = (int)(VSCALE_HT * fPanelHeight);


    // Coordinates for the  horizontal scale along the
    // bottom axis.

    // Use the HSCALE_HT fraction of the panel's height
    fHorzScaleHeight =  (int)(HSCALE_HT * fPanelHeight);
    fHorzScaleY = fFrameY + fFrameHeight;

    // Coordinates for the horizontal label
    fHorzLabelY      = fHorzScaleY  + fHorzScaleHeight;
    fHorzLabelHeight = fPanelHeight - fHorzLabelY;
    fHorzLabelWidth  = fFrameWidth;
    fHorzLabelX      = fFrameX;

  } // getPositions


  /**
    *  The user can assign different colors for the frame elements.
    *  @param line color of frame line.
    *  @param fill color of frame background
    *  @param title color for the title above the frame
    *  @param background the color outside of the plot frame.
    *
   **/
  public void setFrameColors (Color line, Color fill,
                              Color numbers,
                              Color title,
                              Color background) {

    if (line       != null) fFrameLineColor = line;
    if (fill       != null) fFrameFillColor = fill;
    if (numbers    != null) fAxesNumColor   = numbers;
    if (title      != null) fTitleColor     = title;
    if (background != null) fBgColor        = background;

  } // setFrameColors


  /**
    * This method draws the frame, title, and the horizontal axis label.
    * It then invokes paintContents(), which the subclass overrides
    * to draw inside the frame. The paintConents() method is also
    * responsible for invoking drawAxesNumbers() to draw the axes scale
    * numbers.

    *
    * The method first draws the panel and then invokes getPositions()
    * to obtain the coordinates for the frame, the title, labels, etc.
    * It then draws the title and x axis label using the drawText()
    * method and then draws the frame with paintFrame(). At the end it
    * invokes the paintContents () method.
    *
   **/
  public void paintComponent (Graphics g){
    // Set panel background color.
    setBackground (fBgColor);

    // Draw the panel.
    super.paintComponent (g);

    // Get the positions for the titles, labels, etc.
    getPositions ();

    // Draw the top title
    g.setColor (fTitleColor);
    drawText (g, getTitle (),
              fTitleX, fTitleY, fTitleWidth, fTitleHeight,0,
              CENTER);

    // Draw the bottom label
    drawText (g, getXLabel (),
              fHorzLabelX, fHorzLabelY,
              fHorzLabelWidth, fHorzLabelHeight,0,
              CENTER);


    // Draw the plot frame.
    paintFrame (g);

    // Finally, draw the the plot within in the frame
    // with paintConents(). It will also be responsible
    // for drawing the axes scale values.
    // This method must be overriden.
    paintContents (g);

  } // paintComponent


  /** Draw the plot frame. **/
  public void paintFrame (Graphics g) {
    Color old_color = g.getColor ();
    g.setColor (fFrameLineColor);
    g.drawRect (fFrameX, fFrameY, fFrameWidth, fFrameHeight);
    g.setColor (old_color);
  }

  /**
    * This method draws scale numbers along the left vertical and bottom
    * horizontal axes. It uses PlotFormat to format the numbers. The subclass
    * can use its getScaling() method to determine the two data
    * scale arrays.
    *
    * @param g graphics context
    * @param xValue array of data values for horizontal scale axis.
    * @param yValue array of data values for vertical scale axis.
   **/
  void drawAxesNumbers (Graphics g,
                        double [] x_value,
                        double [] y_value) {

    // Check that both axes have scale values to draw.
    if (x_value.length == 0 || y_value.length == 0) return;

    String str_value;
    int type_size = 0;

    // Set the color for the scale numbers.
    g.setColor (fAxesNumColor);

    // Draw the horizontal axis scale numbers.

    // First determine the data scale range.
    double x_range = x_value[x_value.length-1] - x_value[0];
    if (x_range <= 0.0 ) return;

    // Next determine the spacing between numbers along the axis.
    double del_horz = (double)fFrameWidth/(double) (x_value.length);
    int horz;

    // Loop over the horizontal scale value array and draw
    // each value along the axis. Start from the rightmost value
    // and count down.
    for (int i = x_value.length-1; i >= 0 ; i--) {

        // Scale the data value to a pixel coordinate along the x axis.
        horz =  (int)(fFrameWidth * ((x_value[i] - x_value[0])/x_range)
                - del_horz/2.0) + fFrameX;

        // Don't let string go too far to the right. Use no more than
        // the space available.
        if ((horz + del_horz) > fPanelWidth) del_horz = fPanelWidth - horz;

        // Format the x data value into a string
        str_value = PlotFormat.getFormatted (x_value[i],
                                            fXDecimalSci,
                                            fXLoDecimalSci,
                                            2);

        // Now draw the number on the axis within the given box defined
        // by the horz, fHorzScaleY, del_horz, and fHorzScaleHeight values.
        //
        // Use the first value to get the size of the font as selected by
        // drawText() so that the number would fit into the area available.
        if (i == x_value.length-1)
            type_size = drawText (g, str_value,
                                  horz, fHorzScaleY,
                                  (int)del_horz, fHorzScaleHeight,
                                  0, CENTER);
        else
             drawText (g, str_value,
                       horz, fHorzScaleY,
                       (int)del_horz, fHorzScaleHeight,
                       type_size, CENTER);
    }

    // Draw the vertical axis scale numbers.

    // First determine the vertical data scale range.
    double y_range = y_value[y_value.length-1] - y_value[0];
    if (y_range <= 0.0) return;

    // Loop over the vertical scale value array and draw
    // each value along the axis. Start from the topmost value
    // and count down.
    for (int i = y_value.length-1; i >= 0 ; i--) {

        // Convert the y value to a string
        str_value = PlotFormat.getFormatted (y_value[i],
                                            fYDecimalSci, fYLoDecimalSci,
                                            2);

        // Scale the data value to a pixel coordinate along the y axis.
        fVertScaleY = fFrameY + fFrameHeight -
                     (int)(fFrameHeight * ((y_value[i]-y_value[0])/y_range))
                     - fVertScaleHeight;


        // Now draw the number on the axis within the given box defined
        // by the fVertScaleX, fVertScaleY, fVertScaleWidth, and
        // fVertScaleHeight values.
        //
        // Use the first value to get the size of the font as selected by
        // drawText() so that the number would fit into the area available.
        if (i == y_value.length-1)
            type_size = drawText (g, str_value,
                                 fVertScaleX, fVertScaleY,
                                 fVertScaleWidth, fVertScaleHeight,
                                 0, RIGHT);
        else
            drawText (g, str_value,
                     fVertScaleX, fVertScaleY,
                     fVertScaleWidth, fVertScaleHeight,
                     type_size, RIGHT);
    }

  } // drawAxesNumbers


  /**
    *  Draw a string in the center of a given box. The method will
    *  reduce the font size if necessary to fit the string within
    *  the box. You can, however, use the the fixed_type_size_value
    *  parameter to set the text size to a specific. The method won't
    *  draw the string if it doesn't fit in the box.
    *
    *  The position of the string within the box passed
    *  as LEFT, CENTER or RIGHT constant value.
    *
    *  The method returns the value of the font size.
    *
    *  @param g graphics context
    *  @param msg the text to draw
    *  @param x_box horizontal coordinate of box top left corner
    *  @param y_box vertical coordinate of box top left corner
    *  @param box_width horizontal size of the box
    *  @param box_height vertical size of the box
    *  @param fixed_type_size_value set the size of the text rather than
    *  letting method determine it.
    *  @param relative_position position within the box for the text.
   **/
  int drawText (Graphics g, String msg,
                int x_box, int y_box,
                int box_width, int box_height,
                int fixed_type_size_value,
                int relative_position) {

    boolean fixed_type_size = false;
    int type_size = 24;

      // Fixed to a particular type size.
    if (fixed_type_size_value > 0) {
        fixed_type_size = true;
        type_size = fixed_type_size_value;
    }

    int type_size_min = 8;
    int x = x_box,y = y_box;

    do  {
      // Create the font and pass it to the  Graphics context
      g.setFont (new Font ("Monospaced",Font.PLAIN,type_size));

      // Get measures needed to center the message
      FontMetrics fm = g.getFontMetrics ();

      // How many pixels wide is the string
      int msg_width = fm.stringWidth (msg);

      // How tall is the text?
      int msg_height = fm.getHeight ();

      // See if the text will fit in the allotted
      // vertical limits
      if (msg_height < box_height && msg_width < box_width) {
          y = y_box + box_height/2 + (msg_height/2);
          if (relative_position == CENTER)
              x = x_box + box_width/2 -  (msg_width/2);
          else if (relative_position == RIGHT)
            x = x_box + box_width - msg_width;
          else
            x = x_box;
          break;
      }

      // If fixedTypeSize and wouldn't fit, don't draw.
      if (fixed_type_size) return -1;

      // Try smaller type
      type_size -= 2;

    } while (type_size >= type_size_min);

    // Don't display the numbers if they did not fit
    if (type_size < type_size_min) return -1;

    // Otherwise, draw and return positive signal.
    g.drawString (msg,x,y);
    return type_size;
  } // drawText

} // class PlotPanel



import java.util.*;
import java.text.*;

/**
  * This class provides a static method getFormatted that
  * returns a double value as a string in decimal or scientific
  * notation.
 **/
public class PlotFormat
{
  final static DecimalFormat DF1 = new DecimalFormat ("0.0");
  final static DecimalFormat DF2 = new DecimalFormat ("0.00");
  final static DecimalFormat DF3 = new DecimalFormat ("0.000");
  final static DecimalFormat DF4 = new DecimalFormat ("0.0000");

  final static DecimalFormat SF1 = new DecimalFormat ("0.0E0");
  final static DecimalFormat SF2 = new DecimalFormat ("0.00E0");
  final static DecimalFormat SF3 = new DecimalFormat ("0.000E0");
  final static DecimalFormat SF4 = new DecimalFormat ("0.0000E0");

  /**
   * The options include 1 to 3 decimal places. Values below
   * decimalLimit use decimal notation; above this use scientific
   * notation.
   * @param input value
   * @param upper limit before changing to scientific notation
   * @param lower limit before changing to scientific notation
   * @param number of decimal places in the output.
  **/
  public static String getFormatted (double val,
                                     double decimal_hi_limit,
                                     double decimal_lo_limit,
                                     int decimal_places) {
  // If less than decimalLimit, or equal to zero, use decimal style
    if (val == 0.0 || (Math.abs (val) <= decimal_hi_limit &&
        Math.abs (val) > decimal_lo_limit)) {
        switch (decimal_places) {
          case 1 : return DF1.format (val);
          case 2 : return DF2.format (val);
          case 3 : return DF3.format (val);
          case 4 : return DF4.format (val);
          default: return DF1.format (val);
        }
    } else {
      // Create the format for Scientific Notation with E
        switch (decimal_places) {
          case 1 : return SF1.format (val);
          case 2 : return SF2.format (val);
          case 3 : return SF3.format (val);
          case 4 : return SF4.format (val);
          default: return SF1.format (val);
        }
    }
  } // getFormatted

} // class PlotFormat



 

References & Web Resources

Last Update: Feb. 20, 2006

            Tech
Java Tech Graphics
Starting to Plot
  Demo 1
Drawing Panel
  Demo 2
Histogram Display

  Demo 3
Exercises

           Physics
Display Text Data
  Demo 1
Plot Data
  Demo 2
Find Max/Min
  Demo 3
Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.