12.1 Graphics Before Java 1.2

Prior to the introduction of the Java 2D API in Java 1.2, the java.awt.Graphics class provided only rudimentary graphics capabilities. It allowed you to draw lines, draw and fill simple shapes, display text, and draw images and perform basic image manipulation. You could specify a drawing color, a font, a clipping region, and the location of the origin. Notably missing, however, was the ability to specify a line width or rotate or scale drawings. Example 12-1 is a listing of the GraphicsSampler applet that demonstrates all the pre-Java 1.2 basic drawing primitives and attributes. The output of this applet is shown in Figure 12-1.

Figure 12-1. A sampling of graphics primitives
figs/jex3_1201.gif

If you have read Chapter 16, you should understand the structure of this code. This is a very simple applet, however, so you should be able to understand it even before you read that chapter. The init( ) method is called once, when the applet first starts up, and performs one-time initialization. The paint( ) method displays the content of the applet. The Graphics object passed to this method represents the drawing surface of the applet; it allows you to draw anywhere within the bounds of the Applet object. tile( ) and centerText( ) are utility methods defined for the convenience of the paint( ) method. They demonstrate important graphics drawing techniques, but have nothing to do with the applet API.

It is important to understand that the paint( ) method may be called many times. The drawing done in this method doesn't necessarily persist: if the applet is covered by another window and then uncovered, the graphics contained in the applet may well be lost (whether this actually happens depends on the underlying operating system and other factors). In order to restore the graphics, the system invokes the paint( ) method again. Thus, all drawing should be done in the paint( ) method. If you draw anything in the init( ) method, those graphics may be erased and never reappear. (This is one of the serious shortcomings of Example 11-10 and related examples in Chapter 11.)

Example 12-1. GraphicsSampler.java
package je3.graphics; import java.applet.*; import java.awt.*; /**  * An applet that demonstrates most of the graphics primitives in  * java.awt.Graphics.  **/ public class GraphicsSampler extends Applet {     Color fill, outline, textcolor;  // The various colors we use     Font font;                       // The font we use for text     FontMetrics metrics;             // Information about font size     Image image, background;         // Some images we draw with     // This method is called when the applet is first created.     // It performs initialization, such as creating the resources     // (graphics attribute values) used by the paint( ) method.     public void init( ) {         // Initialize color resources.  Note the use of the Color( ) constructor         // and the use of pre-defined color constants.         fill = new Color(200, 200, 200); // Equal red, green, and blue == gray         outline = Color.blue;            // Same as new Color(0, 0, 255)         textcolor = Color.red;           // Same as new Color(255, 0, 0)         // Create a font for use in the paint( ) method.  Get its metrics, too.         font = new Font("sansserif", Font.BOLD, 14);         metrics = this.getFontMetrics(font);         // Load some Image objects for use in the paint( ) method.         image = this.getImage(this.getDocumentBase( ), "tiger.gif");         background = this.getImage(this.getDocumentBase( ), "background.gif");         // Set a property that tells the applet its background color         this.setBackground(Color.lightGray);     }          // This method is called whenever the applet needs to be drawn or redrawn     public void paint(Graphics g) {         g.setFont(font);  // Specify the font we'll be using throughout                  // Draw a background by tiling an image. tile( ) is defined below         tile(g, this, background);                  // Draw a line         g.setColor(outline);            // Specify the drawing color         g.drawLine(25, 10, 150, 80);    // Draw a line from (25,10) to (150,80)         // Draw some text.  See the centerText( ) method below.         centerText("drawLine( )", null, g, textcolor, 25, 10, 150, 80);                  // Draw and fill an arc         g.setColor(fill);         g.fillArc(225, 10, 150, 80, 90, 135);         g.setColor(outline);         g.drawArc(225, 10, 150, 80, 90, 135);         centerText("fillArc( )", "drawArc( )", g, textcolor,225,10,150,80);                  // Draw and fill a rectangle         g.setColor(fill);         g.fillRect(25, 110, 150, 80);         g.setColor(outline);         g.drawRect(25, 110, 150, 80);         centerText("fillRect( )", "drawRect( )", g, textcolor, 25, 110, 150, 80);                  // Draw and fill a rounded rectangle         g.setColor(fill);         g.fillRoundRect(225, 110, 150, 80, 20, 20);         g.setColor(outline);         g.drawRoundRect(225, 110, 150, 80, 20, 20);         centerText("fillRoundRect( )", "drawRoundRect( )", g, textcolor,                    225, 110, 150, 80);                  // Draw and fill an oval         g.setColor(fill);         g.fillOval(25, 210, 150, 80);         g.setColor(outline);         g.drawOval(25, 210, 150, 80);         centerText("fillOval( )", "drawOval( )", g, textcolor, 25, 210, 150, 80);                  // Define an octagon using arrays of X and Y coordinates         int numpoints = 8;         int[  ] xpoints = new int[numpoints+1];         int[  ] ypoints = new int[numpoints+1];         for(int i=0; i < numpoints; i++) {             double angle = 2*Math.PI * i / numpoints;             xpoints[i] = (int)(300 + 75*Math.cos(angle));             ypoints[i] = (int)(250 - 40*Math.sin(angle));         }         // Draw and fill the polygon         g.setColor(fill);         g.fillPolygon(xpoints, ypoints, numpoints);         g.setColor(outline);         g.drawPolygon(xpoints, ypoints, numpoints);         centerText("fillPolygon( )", "drawPolygon( )", g, textcolor,                    225, 210, 150, 80);                  // Draw a 3D rectangle (clear an area for it first)         g.setColor(fill);         g.fillRect(20, 305, 160, 90);         g.draw3DRect(25, 310, 150, 80, true);         g.draw3DRect(26, 311, 148, 78, true);         g.draw3DRect(27, 312, 146, 76, true);         centerText("draw3DRect( )", "x 3", g, textcolor, 25, 310, 150, 80);                // Draw an image (centered within an area)         int w = image.getWidth(this);         int h = image.getHeight(this);         g.drawImage(image, 225 + (150-w)/2, 310 + (80-h)/2, this);         centerText("drawImage( )", null, g, textcolor,  225, 310, 150, 80);     }          // Utility method to tile an image on the background of the component      protected void tile(Graphics g, Component c, Image i) {         // Use bounds( ) instead of getBounds( ) if you want         // compatibility with Java 1.0 and old browsers like Netscape 3         Rectangle r = c.getBounds( );             // How big is the component?         int iw = i.getWidth(c);                  // How big is the image?         int ih = i.getHeight(c);         if ((iw <= 0) || (ih <= 0)) return;                 for(int x=0; x < r.width; x += iw)       // Loop horizontally             for(int y=0; y < r.height; y += ih)  // Loop vertically                 g.drawImage(i, x, y, c);         // Draw the image     }          // Utility method to center two lines of text in a rectangle.     // Relies on the FontMetrics obtained in the init( ) method.     protected void centerText(String s1, String s2, Graphics g, Color c,                               int x, int y, int w, int h)     {         int height = metrics.getHeight( );  // How tall is the font?         int ascent = metrics.getAscent( );  // Where is the font baseline?         int width1=0, width2 = 0, x0=0, x1=0, y0=0, y1=0;         width1 = metrics.stringWidth(s1);  // How wide are the strings?         if (s2 != null) width2 = metrics.stringWidth(s2);         x0 = x + (w - width1)/2;           // Center the strings horizontally         x1 = x + (w - width2)/2;         if (s2 == null)                    // Center one string vertically             y0 = y + (h - height)/2 + ascent;         else {                             // Center two strings vertically             y0 = y + (h - (int)(height * 2.2))/2 + ascent;             y1 = y0 + (int)(height * 1.2);         }         g.setColor(c);                     // Set the color         g.drawString(s1, x0, y0);          // Draw the strings         if (s2 != null) g.drawString(s2, x1, y1);     } } ]]> <?import end_imported_file file=Examples/je3/graphics/GraphicsSampler.java?><!--RESUME EDITING-->

12.1.1 Running the Applet

If you have not yet read Chapter 16, you may not know how to run the applet listed in Example 12-1. All you need to do is include the following <applet> tag in an HTML file, place the file in the same directory as the GraphicsSampler class file, and load the HTML file into a web browser:

<applet code="je3/graphics/GraphicsSampler.class"  codebase="../../"         width=400 height=400> </applet>

You'll find this tag in a file named GraphicsSampler.html in this book's online example archive.

Note that GraphicsSampler calls the Java 1.1 method getBounds( ), so you must use a browser that supports Java 1.1, such as Netscape Navigator 4.0 or later. You can also use the appletviewer application that comes with the Java SDK:

% appletviewer GraphicsSampler.html

12.1.2 Fonts

To enhance cross-platform portability, Java 1.0 and 1.1 defined only a handful of fonts (as we'll see later, Java 1.2 allows you to use any font available on the underlying system). In Java 1.0, these fonts were TimesRoman, Helvetica, and Courier. In Java 1.1, the fonts were given preferred logical names: Serif, SansSerif, and Monospaced. Each font is available in four styles and any number of sizes. Example 12-2 shows the listing of the FontList applet, which displays each of the standard fonts in each of the available styles. Its output is shown in Figure 12-2.

Figure 12-2. The standard fonts and styles
figs/jex3_1202.gif
Example 12-2. FontList.java
package je3.graphics; import java.applet.*; import java.awt.*; /**  * An applet that displays the standard fonts and styles available in Java 1.1  **/ public class FontList extends Applet {     // The available font families     String[  ] families = {"Serif",         // "TimesRoman" in Java 1.0                          "SansSerif",     // "Helvetica" in Java 1.0                          "Monospaced"};   // "Courier" in Java 1.0          // The available font styles and names for each one     int[  ] styles = {Font.PLAIN, Font.ITALIC, Font.BOLD, Font.ITALIC+Font.BOLD};     String[  ] stylenames = {"Plain", "Italic", "Bold", "Bold Italic"};          // Draw the applet.       public void paint(Graphics g) {         for(int f=0; f < families.length; f++) {        // for each family             for(int s = 0; s < styles.length; s++) {        // for each style                 Font font = new Font(families[f],styles[s],18); // create font                 g.setFont(font);                                // set font                 String name = families[f] + " " +stylenames[s]; // create name                 g.drawString(name, 20, (f*4 + s + 1) * 20);     // display name             }         }     } }

12.1.3 Colors

A color in Java is represented by the java.awt.Color class. The Color class defines a number of constants that refer to predefined Color objects for commonly used colors, such as Color.black and Color.white. You can also create your own custom Color object by specifying the red, green, and blue components of the color. These components may be specified as integers between 0 and 255 or as float values between 0.0 and 1.0. Additionally, the static getHSBColor( ) method allows you to create a Color object based on hue, saturation, and brightness values. As of Java 1.1, the java.awt.SystemColor subclass of Color defines a number of constant SystemColor objects that represent standard colors in the system desktop palette. You can use these colors to make your application match the desktop color scheme.

Example 12-3 lists the ColorGradient applet, which uses Color objects to produce the color gradient shown in Figure 12-3. This applet uses applet parameters in the HTML file to specify the starting and ending colors of the gradient. You can use the applet with HTML tags like the following:

<applet code="je3/graphics/ColorGradient.class" codebase="../../"         width=525 height=150>     <param name="startColor" value="#a06060"> <!-- light red -->     <param name="endColor" value="#ffffff">   <!-- white --> </applet>
Figure 12-3. A color gradient
figs/jex3_1203.gif
Example 12-3. ColorGradient.java
package je3.graphics; import java.applet.*; import java.awt.*; /** An applet that demonstrates the Color class */ public class ColorGradient extends Applet {     Color startColor, endColor;   // Start and end color of the gradient     Font bigFont;                 // A font we'll use     /**       * Get the gradient start and end colors as applet parameter values, and      * parse them using Color.decode( ).  If they are malformed, use white.      **/     public void init( ) {         try {             startColor = Color.decode(getParameter("startColor"));             endColor = Color.decode(getParameter("endColor"));         }         catch (NumberFormatException e) {             startColor = endColor = Color.white;         }         bigFont = new Font("Helvetica", Font.BOLD, 72);     }     /** Draw the applet.  The interesting code is in fillGradient( ) below */     public void paint(Graphics g) {         fillGradient(this, g, startColor, endColor);  // display the gradient         g.setFont(bigFont);                    // set a font         g.setColor(new Color(100, 100, 200));  // light blue         g.drawString("Colors!", 100, 100);     // draw something interesting     }     /**      * Draw a color gradient from the top of the specified component to the      * bottom.  Start with the start color and change smoothly to the end       **/     public void fillGradient(Component c, Graphics g, Color start, Color end) {         Rectangle bounds = this.getBounds( );  // How big is the component?         // Get the red, green, and blue components of the start and end         // colors as floats between 0.0 and 1.0.  Note that the Color class         // also works with int values between 0 and 255         float r1 = start.getRed( )/255.0f;         float g1 = start.getGreen( )/255.0f;         float b1 = start.getBlue( )/255.0f;         float r2 = end.getRed( )/255.0f;         float g2 = end.getGreen( )/255.0f;         float b2 = end.getBlue( )/255.0f;         // Figure out how much each component should change at each y value         float dr = (r2-r1)/bounds.height;         float dg = (g2-g1)/bounds.height;         float db = (b2-b1)/bounds.height;         // Now loop once for each row of pixels in the component         for(int y = 0; y < bounds.height; y++) {             g.setColor(new Color(r1, g1, b1));    // Set the color of the row             g.drawLine(0, y, bounds.width-1, y);  // Draw the row             r1 += dr; g1 += dg; b1 += db;         // Increment color components         }     } }

12.1.4 Simple Animation

Animation is nothing more than the rapid drawing of a graphic, with small changes between "frames," so the object being drawn appears to move. Example 12-4 shows the listing for an applet that performs a simple animation: it moves a red circle around the screen. The applet uses a Thread object to trigger the redraws. The technique used here is quite simple: when you run the applet, you may notice that it flickers as the ball moves.

Later in this chapter, we'll see another animation example that uses more advanced techniques to prevent flickering and produce smoother animation.

Example 12-4. BouncingCircle.java
package je3.graphics; import java.applet.*; import java.awt.*; /** An applet that displays a simple animation */ public class BouncingCircle extends Applet implements Runnable {     int x = 150, y = 50, r = 50;  // Position and radius of the circle     int dx = 11, dy = 7;          // Trajectory of circle     Thread animator;              // The thread that performs the animation     volatile boolean pleaseStop;  // A flag to ask the thread to stop          /** This method simply draws the circle at its current position */     public void paint(Graphics g) {         g.setColor(Color.red);         g.fillOval(x-r, y-r, r*2, r*2);     }          /**      * This method moves (and bounces) the circle and then requests a redraw.      * The animator thread calls this method periodically.      **/     public void animate( ) {         // Bounce if we've hit an edge.         Rectangle bounds = getBounds( );         if ((x - r + dx < 0) || (x + r + dx > bounds.width)) dx = -dx;         if ((y - r + dy < 0) || (y + r + dy > bounds.height)) dy = -dy;         // Move the circle.         x += dx;  y += dy;         // Ask the browser to call our paint( ) method to draw the circle         // at its new position.         repaint( );     }          /**      * This method is from the Runnable interface.  It is the body of the       * thread that performs the animation.  The thread itself is created       * and started in the start( ) method.      **/     public void run( ) {         while(!pleaseStop) {           // Loop until we're asked to stop             animate( );                       // Update and request redraw             try { Thread.sleep(100); }       // Wait 100 milliseconds             catch(InterruptedException e) {  } // Ignore interruptions         }     }     /** Start animating when the browser starts the applet */     public void start( ) {         animator = new Thread(this);   // Create a thread         pleaseStop = false;            // Don't ask it to stop now         animator.start( );              // Start the thread.         // The thread that called start now returns to its caller.         // Meanwhile, the new animator thread has called the run( ) method     }          /** Stop animating when the browser stops the applet */     public void stop( ) {         // Set the flag that causes the run( ) method to end         pleaseStop = true;     } }


Java Examples in a Nutshell
Java Examples in a Nutshell, 3rd Edition
ISBN: 0596006209
EAN: 2147483647
Year: 2003
Pages: 285

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net