Introduction to Java. A tutorial from IEEE in cooperation with A-SQUARE, Inc. May 2001

© 2000-2001 A-Square, Inc. Reston Virginia

SourceCode for Exercise 2, Banner2b

This HTMLdocument has three Java documents which should each be copied into their own files and given the name of the class followed by .java . Note, however, that the source of Logo.java is identical to the source in Exercise2, Banner2a

As always you get the sourcecode by selecting and copying any text between the two > that separate the source texts from the rest of this HTML document.

Banner2b.java

IEEELogo.java

Logo.java

Banner2b.java

>
/*
 * Banner2b applet  Version 2.0
 * 
 * Jan Aminoff , September 2000
 * © A-Square 1997-2000.
 *
 */

import java.awt.*;
import java.applet.Applet;


/**
 * This Applet demonstrates object oriented programming. 
 * Compared to the Banner1 example, we have broken out the
 * code relating to a specific logo and how it moves. As a result
 * we have a much simpler applet that with minimum modifications 
 * may be used for the display of other logos.
 * 
 * author Jan Aminoff/  © A-Square 1997
 * version 2.0, modified September 2000, for use at IEEE/A-Square 
 * Introduction to Java, tutorial.
 * 
 * This version should compile and run under JDK 1.0.2
 */

public class Banner2b extends Applet implements Runnable {
   ///////////////////////////////////////////////////////////////////////////
   // The Banner1 class declares the following public methods and no public
   // variables: init, start, run, stop, mouseDown.
   ///////////////////////////////////////////////////////////////////////////   
   /*
    * The init() method is prescribed by the Applet class, or more
    * precisely, the init() method here overrides a method in the
    * Applet class that Banner2 extends. 
    */

   
   public void init() {
      // Actually all initial processing has been moved to the manageScreen
      // method which takes care of a modified screen/window/applet size.
      manageScreen();      
   }  

   private void manageScreen(){
      /* In this case we will add a modification to the Banner2 applet.
       * We will handle the case when the size of the applet has changed.
       * This will never happen in a browser where the size is given in 
       * the Applet tag. In the AppletWiever, however, you may change the
       * size of the window. The manageScreen method is called when such a
       * change is detected and adjusts the processing by getting a new 
       * appropriately sizedbuffer, Since maxx and maxy are initilized to 0,
       * the first use of the manageScreen is in init saving some typing.
       */

      int mx1 = size().width;   // Get the width of the screen/window
      int my1 = size().height;  // Get the height of the window
      // Get the doublebuffer if you can
      // but first get rid of the old one if there is one
      if (imagebuffer != null){
         imagebuffer = null;
      } 
      try {                      
         // allocate an offscreen graphics
         imagebuffer = createImage(mx1, my1);
         gc = imagebuffer.getGraphics();         
      }
      catch (Exception e) { gc = null; } 
      // Since we have new values for the screensize we had better
      // get a new version of the logo to ensure it is inside the new screen.
      logo = new IEEELogo(mx1, my1, size);   //IEEE specific
      // and set the maximum speed for the new logo.
      logo.setMaxSpeed(maxv);
      // Finally we have to make sure that maxx and maxy gets the right values
      maxx = mx1;
      maxy = my1;
   } // End of manageScreen
   
  /* Normally private variables would be placed at the end of the class
   * source. We are giving them here to allow them to be considered in the 
   * textual context where they are set initially.
   */
   private Graphics     gc;  // used for drawing
   private Image        imagebuffer; // Used for drawing when double buffering
   // The applet appears as a rectangle with upper left coordinates (0, 0)
   // and lower right coordinates (maxx, maxy),.
   private int maxx = 0;         // The right edge of the applet
   private int maxy = 0;         // The lower edge of the applet
   private int maxv = 8;         // Max speed of logo
   private int size = 35;        // Size of logo
   private IEEELogo logo;     // IEEE specific
  
   // End of init and declarations of private variables initiated in init.
  

  /*
   * The following three public methods: start, stop and run implement
   * the Runnable Interface. It is useful to allow programs outside the Applet
   * control the animation.
   */
 
   public void start() {
      if (clock == null) {
         clock = new Thread(this, "Banner");
         clock.start();
      }
   }

  /*
   * The run method interupts execution for stime milliseconds between repaints.
   * This is a crude way to get the applet to execute frames at a rate which is
   * relatively independent of processor speed.
   */

   public void run() {
      while (clock != null) {
         try {
            clock.sleep(stime);       //wait for stime milliseconds.
         }
         catch (InterruptedException e) {}  //resume
         repaint();
      }
      clock = null;
   }
   
   public void stop() {
      if (clock != null) {
         clock.stop();
         clock = null;
      }
   }
   private Thread clock = null;  //A thread is a thread of execution

  /* If dtime is 1000 milliseconds then stime is about 25 milliseconds which
   * means there are about 40 frames in a second if the time to do the 
   * actual animation is ignored. This should give a smooth animation.
   */
   private int dtime=1000;       
   private int stime=dtime/40;

   // End of Runnable related methods and variables  
                                 

  /*
   * mouseDown, Library method called when the user presses the mouse.
   *
   * The mouseDown method is now depreciated and replaced with more general
   * but also more complex methods for event handling. The Java virtual 
   * machine automatically invokes the mouseDown method when the user
   * presses the mouse button. In this case we are not intersted in
   * xd and yd, which would give the coordinates for the mouse click.
   */

   public boolean mouseDown(java.awt.Event evt, int xd, int yd) {
      if (move){
         logo.stopMove();
      }else{ 
         logo.resumeMove();
      }  
      move=!move;
      return true;  
   }
   
   private boolean move=true; // This variable says that the logo is moving

   // End of mousDown method and related private variables

  /*
   * The update method is prescribed by the Applet.
   *
   * The update method is called periodically. It has two branches depending
   * on wether or not we were succesfull in securing us a buffer for double
   * buffering.
   * If the imagebuffer is null  we have to paint this applet directly
   * on the graphichs context g.
   *
   * This is also where we will track if the size of the window has changed.
   * If it has, we call the manageChange metod again.
   */
   
   public void update(Graphics g){
      int xm1 = size().width;
      int ym1 = size().height;
      if ((xm1 != maxx)||(ym1 != maxy)){ //Has the size changed?
         manageScreen();
      }
      if (imagebuffer != null) {
         paintBanner(gc);
         g.drawImage(imagebuffer, 0, 0, this);
      }
      else {
         g.clearRect(0, 0, maxx, maxy);
         paintBanner(g);
      }
   }

   ///////////////////////////////////////////////////////////////////////////
   // Following the declarations of public methods and variables, the Java 
   // coding conventions require the positioning of private methods and 
   // variables. The Banner2 class has the following private methods:
   // paintBanner, manageScreen, and printString which may be considered .
   // a utility method.
   ///////////////////////////////////////////////////////////////////////////

  /*
   * The paintBanner method paints the whole rectangle (0, 0, maxx, maxy)
   * using the graphics context g. It starts by painting it all light gray.
   * It then draws and moves the logo. Compare to Banner2a with ASquareLogo!
   * It then draws the three strings s1, s2 and s3.
   * Note that all information of the  movements is in the Logo class
   */ 

   private void paintBanner(Graphics g){
       // This method paints the whole rectangle (0,0, maxx, maxy) 
      g.setColor(Color.white);     // Looks better with IEEE logo
      g.fillRect(0, 0, maxx, maxy);    // Paint the screen white
      //For IEEE it looks better to have the Logo under the strings
      logo.drawLogo(g);       // Draw the logo 
      logo.moveLogo();        // Move the logo           
      printString(g, s1, maxx,45  ,24);// Draw the three strings
      printString(g, s2, maxx,70  ,12);
      printString(g, s3,maxx,maxy-5,9);
      
   }   
   
   private String s1="Welcome to Introductory Java";
   private String s2="Jan Aminoff, Instructor";
   private String s3="Also inventor of RARTª, Random Art for the Internet";

   // End of paintBanner and declarations of strings
   
   
   
   /* 
    * Standard methods
    */

   // The following prints the String st using the color blue and the font 
   // Helvetica at pointsize s according to coordinates x and y.
   private static void printString(Graphics g, String st, int x, int y, int s)
   {//Decided to fancy it up so the text is centered between 0 and x   May 8, 1998  
      Font  Hel = new Font("Helvetica", Font.BOLD, s);
      g.setFont(Hel);
      FontMetrics fm = g.getFontMetrics(Hel);
      int cx=fm.stringWidth(st);
      cx=(x-cx)/2;      
      g.setColor(Color.blue);
      g.drawString( st, cx, y );
         
   }  // End of standard methods  
      
}  // End of Banner2b
>

Top

IEEELogo.java

>
/* IEEELogo.java    Version 2.0  030105
 *
 * This class is used to provide a floating IEEE logo. 
 * It is in particular used in the Banner2b applet, 
 *
 * Copyright (c) A-Square Inc., 
 * 175 Richdale Ave, Cambridge MA 02140
 * All Rights Reserved.
 */

import java.awt.*;

public class IEEELogo extends Logo{
    /** In this class we only need to define the two methods
     * declared abstract in Logo:
     * drawLogo(Graphics g)which draws the object of size s centered at point p
     * eraseLogo(Graphics g, Color c) which erases the object by drawing a 
     * rectangle of size s and the color c centered at point p
     *
     */

     // The following constructor invokes the super constructor, that is the
     // constructor of the class this class extends
     public IEEELogo(int xmax, int ymax, int size){
        super(xmax,ymax,size);
        // Import a gif image. This works only because Logo extends Component
        // and precludes the use of this applet in a JDK 1.0.2 environment.
		// It also causes a security exception when executed in a browser.
		// See Exercise 3d for how the picture or any resource may be imported
		// in a Rart universe also when executing in an applet environment.
        Image logo1 = getRartImage("num3blu.gif");
        logo = logo1.getScaledInstance(2*size, 2*size, Image.SCALE_FAST);
     }
     
     public void drawLogo(Graphics g){
        int w=s;    //half width
        int h=s;    //half height         
        g.drawImage(logo, p.x-w, p.y-h, this);
        
    }
    public void eraseLogo(Graphics g, Color c){
        // Erases the IEEE logo by drawing a rectangle of size
        // 2*s by 2*s centered at p
            int w=s;
            int h=s;
            g.setColor(c);
            g.fillRect(p.x-w,p.y-h,2*w,2*h);
    }
    private Image logo;
}
>

Top

Logo.java

Note: Identical to class with same name in the source for Banner2a

>
/**
 * Logo.java        version 1.0   000910
 * 
 * This is an example of an abstract class. We prescribe a behavior common to
 * all concrete implementations  of this class, which prescribe the way Logo 
 * objects float on the screen. We leave the specifics on how an actual Logo
 * looks to the programmer who uses the class.
 * 
 * Copyright (c) A-Square Inc., 
 * 1648 Waters Edge Lane, Reston, VA 20190
 * All Rights Reserved.
 * 
 */

import java.awt.*;


public abstract class Logo extends Component{
/* In an abstract class some items are left for the extending classes to
 * define. In this case the extending classes will define the look of the
 * floating objects.
 * Movement is defined in the moveLogo() method and can be influenced by the
 * MouseDown() method.
 * Jan Aminoff, A-Square, September 2000.
 */

    
    public Logo(int xm, int ym, int size){
    /**
     * This constructor initiates a Logo of size size floating within
     * the rectangle with (0.0) as the upper right and (xm, ym) at lower left.
     */
        maxx = xm;
        maxy = ym;
        p= new Point( RND(maxx), RND(maxy));
        // d.dbg("Point : "+p.x+ ", "+p.y);
        s = size;  
        maxv = 2+(maxx+maxy)/100;
        dx=setSpeed(maxv);
        dy=setSpeed(maxv);
    }
    
    
    
   
    public abstract void drawLogo(Graphics g);
    /* Abstract method draw
     * Draws a Logo of size s pixels at Point p (Coordinates p.x and p.y)
     * using the Graphics Context g
     */
    
    public abstract void eraseLogo(Graphics g, Color c);
    /* Abstract method erase
     * erases a Logo of size s pixels centered at p by drawing
     * it using the Color c, for example the background color, using g
     */
    
    public void moveLogo(){
    /*  This is NOT an abstract method! It encapsulates the moving of a 
     *  point bouncing as we have seen a number of times.
     */
      int x = p.x;
      int y = p.y;      
      x += dx;
      y += dy;    
      // check to see if point  hit the edge    
      if (x < 0 || x > maxx ){          // Check to see if the point hit the edge in x-direction
         dx = (x < 0)? ABS(dx) : - ABS(dx);     //Ensure point always moving toward center
         x += 2*dx;                 //Double back
         dy = setSpeed(maxv);        //change speed in y-direction
      }
      
      if (y < 0 || y > maxy ){
         dy = (y < 0)?  ABS(dy) : - ABS(dy); 
         y += 2*dy;
         dx = setSpeed(maxv);       //change speed in x-direction
      }
      p = new Point(x,y);
      
   }
   
   public void setMaxSpeed( int vmax){
      maxv = vmax;
   }

   public void stopMove(){
      dx1=dx;
      dx=0;
      dy1=dy;
      dy=0;
   }


   public void resumeMove(){
      dx=dx1;
      dy=dy1;
         
   }
    
    
    private int setSpeed(int mv){
   // We will also define a method to generate a change of speed based on 
   // a maximum speed mv
        int v;
        do v = mv/2- RND(mv); 
        while (v ==0);
        return v;
    }

   // The following methods are protected. This means the methods are available
   //  to methods extending the Logo class but not elsewhere.

   protected Image getRartImage(String s){
   // This method is identical to one provided in the Universe class
   // The point here is to allow the extensions of the Logo class to
   // import and display their own pictures.
   // However, while this works fine in the appletviewer, it causes an
   // security exception when run in a browser. 
         return Toolkit.getDefaultToolkit().getImage(s);
     }
    
    // RND generates any of the integers in the interval 0 to max - 1.
   protected static int RND(int max)
   {
      return (int)(java.lang.Math.random() * max);
   }

   // ABS(x) returns the absolute value of the integer x
   protected static int ABS(int x){
      return ((x>0)? x: -x);
   }

   // The following two variables are protected, that is their values are
   // at any time available to any class extending the Logo class.
   // In particular the values are used to draw the object in the draw 
   // method
   protected Point p;         // The center of the object. 
                                // A point with coordinates p.x and p.y
   protected int s;            // A measure of the size of the object

    //Here we list the private variables used by the class
    
    private int maxx;   //Windowsize in x-direction
    private int maxy;   //Windowsize in y-direction
    private int maxv;   //Maximum sped in any direction, pixels per frame
    private int dx;     //Current speed in x-direction
    private int dy;     //Current speed in y-direction

    private int dx1;    //Keeper for speed in x-direction
    private int dy1;    //Keeper for speed in y-direction
   
}
>

Top