© 2000-2003 A-Square, Inc. Cambridge, MA
Banner1 in its several variations is considered in Exercise 1 of the Introduction to Java Tutorial
public class Banner1 extends Applet implements Runnable
public void update(Graphics g)
private void paintBanner(Graphics g)
The source code to Banner1 is available in Banner1_source.html and as Java source text in Banner1.java in the folder MyEX1. The code is richly commented and the interested reader can deduce many features from the commented code. We will here introduce some basic Java concepts, however. The intent is that you shall have an idea of what is generally applicable on the one hand and specific to our examples on the other.
import java.awt.*;
import java.applet.Applet;
The AWT package contains most anything having to do with graphics. AWT, the Abstract Windowing Toolkit, was given its main features with the first release of Java and remarkably little has changed with later releases. This means that browsers that supported the first Java release (JDK 1.0.2) will display whatever graphics you can devise using the AWT. In other words, Java offered platform independent graphics from the very beginning, and while many other aspects have been drastically changed, Java 1.0.2 still offers a comprehensive set of graphics tools.
We also import the Applet class of the applet package. Some methods, notably init() and update(g) are prescribed by the Applet class, or more precisely, by overriding init() and update(g) in the Applet class we make our applet, Banner1, behave in a way that is useful to us.
public class Banner1 extends Applet implements Runnable {
In this declaration of the Banner1 class we say a number of things:
The init() method is called by the runtime system and is used to set up whatever is needed to initiate the applet. In the case of Banner1 these initiations comprise:
A note about size(). The method size() is defined in the abstract class Component in AWT. From Component is derived another abstract class Container. From Container is derived Panel, and as it happens the Applet class extends Panel. Since Banner1 extends Applet, we can call upon the size() method and during execution, the VM will go up in the class hierarchy until it actually finds an implemented size() method and execute it.
Another thing to note about size(): The name of the method does not follow the Java code conventions. In Java 1.1 the correctly named getSize() method was added and you will, in fact, get a "Warning" when compiling Banner1 that the method size() is "Depreciated". This is a warning you should ignore since we wish Banner1 to execute also in some very old browsers which may not have implemented getSize() and since all newer releases of Java have retained the older version of size() for backward compatibility.
public void stop()
These two methods actually exist in Applet where they are indications on when to initiate/resume or stop execution of the applet.We have implemented our two methods with the same signature (signature means the name and parameter types, in this case no parameters) as the two methods given in the Applet class. This means that when the VM looks for any of these two methods, it will find our implementation which is then executed instead of the one in Applet. We say that we override the start and stop methods in the class Applet that Banner1 extends. This is an important concept in Object Oriented programming because it allows us to tailor our class according to its own requirements by redefining methods that we know the run time system will execute at appropriate times.
If you inspect the packages that come with JDK, you can actually check out the source code provided. If we check out start() in Applet.java (found as part of the java.applet package,) we get the following.
This is a good example of the use of comments which are provided like this throughout the Java JDK source and should serve as model on how to provide comments in a professional way.: You can see things that look like HTLM tags embedded in the text. There is actually included in Java a system to extract comments from source and provide them in browser viewable form. The tool to extract correctly written comments is part of the java package. It can invoked through javadoc [options] filenames, the details of which you may find in any reference on Java.
/**
* Called by the browser or applet viewer to inform
* this applet that it should start its execution. It is called after
* the <code>init</code> method and each time the applet is revisited
* in a Web page.
* <p>
* A subclass of <code>Applet</code> should override this method if
* it has any operation that it wants to perform each time the Web
* page containing it is visited. For example, an applet with
* animation might want to use the <code>start</code> method to
* resume animation, and the <code>stop</code> method to suspend the
* animation.
* <p>
* The implementation of this method provided by the
* <code>Applet</code> class does nothing.
*
* @see java.applet.Applet#destroy()
* @see java.applet.Applet#init()
* @see java.applet.Applet#stop()
* @since JDK1.0
*/
public void start() {
}
The method stop looks the same and has similar comments:
public void stop() {
}
that is, the methods do nothing in Applet. However these do nothing methods are called at appropriate times by the runtime system and so, if you wish something to happen when the applet starts or stops executing, you override them as we have done in Banner1.
The run method is required to implement the Runnable interface. In Java a class can have only one parent and interfaces are a way of overcoming this limitation. That means, that when you wish for your class to have a particular functionality you can specify that it implements a suitable interface. In the case of Runnable, the interface definition looks as follows:
/*
* @(#)Runnable.java 1.14 98/07/01
*
* Copyright 1995-1998 by Sun Microsystems, Inc.,
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Sun Microsystems, Inc. ("Confidential Information"). You
* shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Sun.
*/
package java.lang;
/**
* The <code>Runnable</code> interface should be implemented by any
* class whose instances are intended to be executed by a thread. The
* class must define a method of no arguments called <code>run</code>.
* <p>
* This interface is designed to provide a common protocol for objects that
* wish to execute code while they are active. For example,
* <code>Runnable</code> is implemented by class <code>Thread</code>.
* Being active simply means that a thread has been started and has not
* yet been stopped.
* <p>
* In addition, <code>Runnable</code> provides the means for a class to be
* active while not subclassing <code>Thread</code>. A class that implements
* <code>Runnable</code> can run without subclassing <code>Thread</code>
* by instantiating a <code>Thread</code> instance and passing itself in
* as the target. In most cases, the <code>Runnable</code> interface should
* be used if you are only planning to override the <code>run()</code>
* method and no other <code>Thread</code> methods.
* This is important because classes should not be subclassed
* unless the programmer intends on modifying or enhancing the fundamental
* behavior of the class.
*
* @author Arthur van Hoff
* @version 1.14, 07/01/98
* @see java.lang.Thread
* @since JDK1.0 * @see Thread
*/
public
interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
*
* @see java.lang.Thread#run()
* @since JDK1.0
*/
public abstract void run();
}
We here encounter the method qualifier abstract which is used to qualify a method which at the time of its abstract definition only has a signature and no body. The body will be provided in the code that implements the interface. The idea of abstraction is an exceedingly important tool in Object Oriented programming because it allows a systems architect to think from the top down rather than from the bottom up.
Notice, that only one method, run(),has to be defined in order to implement the interface. In our case we use it to ensure the periodic execution of repaint() in such a way as to get a consistent apparent speed of the animation regardless of the speed of the platform/VM combination used for its execution.
public boolean mouseDown(java.awt.Event
evt, int xd, int yd)
We have elected to include one method related to event handling. JDK 1.0.2 offered the kind of event handling exemplified in the mouseDown method. If you were interested in the mouse button being pressed you implemented a public boolean method mouseDown with a signature as shown. The body of the method would have access to data relating to the event, in the case of a mouseDown, the screen coordinates xd, yd, of the location of the cursor when the user pressed the mouse. In our case we have implemented a very simple action that stops and resumes the movement of the logo.
An event handling method in JDK 1.0, as the one described, is always boolean, that is it returns true or false according to whether or not the event was actually processed in the method. This ensures that any event is either processed by the method, (return true; as in this case) or propagated in the dynamic hierarchy if not processed when the method returns false.
The update() method is called indirectly by way of repaint() in the run() cycle. It has two branches depending on whether or not we have double buffering. If we do have double buffering we use paintBanner(gc) to paint to the gc graphics. We then use drawImage to move the repainted frame from gc, to g. If we donot have double buffering, we use paintBanner(g) to draw directly to g.
In this applet we redraw the whole applet for each frame. Thus, paintBanner(g) starts by clearing the screen by redrawing it using a prescribed background color, lightgray. We then paint the logo using drawAsquare. Then we add the three strings which has the effect of the logo moving under the text. If you reverse the order, i.e. draw the strings before the logo, the logo will appear to float above the strings. Finally we move the center of the logo.
To move the logo we add dx and dy to the coordinates x, y, of the center of the logo. Normally this is enough and you see the logo moving in a straight line. However, if the center should hit the edge of the rectangle bounded by (0,0) on upper right and (xmax,ymax) on lower left we do something more. First, we reverse the direction of the center so that it always moves inward. Second, we generate a new speed component parallel to the edge we hit. This has the desired effect of the logo appearing to bounce randomly.
The following statement may be used to illustrate how a while loop is used to generate a speed component in the x-direction.
do dx = maxv/2-RND(maxv); while (dx ==0);
RND(maxv) generates one of the integers 0,1,2,3 . . . maxv-1 with equal probability. If maxv is even, say 6, the combination maxv/2-RND(maxv) generates the numbers -2,-1,0,1,2 with equal probability. This would be OK except that we have to exclude dx equal 0, because if it is 0, the logo would stop moving in the x-direction and would eventually stop alltogether. For this reason we have the combination in a do-while loop that keeps on generating a new dx until it finds one that is non 0. Think about it!
Finally we will briefly discuss the method that actually draws the A-Square logo. In Java you have certain colors predefined. There are much more involved and sophisticated methods for handling color, but drawAsquare uses the simplest possible.
The method has the parameters Graphics g, int x, int y and int s. g is used so you can draw the logo two ways, either directly on the screen or on the window buffer if double buffering is available. x and y give the center of the logo. This is convenient since we allow the center point to bounce around. And finally s determines the size of the logo in pixels. It turns out to be 2 x s pixels wide and 2.4 x s pixels tall.
This is a good place to introduce the concept of a cast. Java is a strongly typed language which means that any variable has a type and that you have to pay attention when assigning a value to a variable that everything is OK. Since the computer screen is made up of distinct pixels, it makes sense to work in integers when we define objects on the screen. Now, in this example the parameter s is an integer. We multiply it with 1.2 to get the ratio of width to height correct. When we do the multiplication 1.2*s, we will get a number that is not an integer. We need to convert this non integer to an integer and we do this with a cast which in Java has the form (int) when we convert to an integer. This results in the following statement where we declare the variable h to be an integer with the approximate value of 1.2 times s:
int h=(int) (1.2*s);
Notice that it is necessary put parenthesis around the multiplication. Otherwise the cast would be applied to 1.2 and would convert 1.2 to the integer 1 resulting in a square logo. Which was what we wanted to avoid by introducing the height h different from s.
Finally we have a number of utility methods. They have the property that their output only depend on their input as given by the parameters each time they are called. This means that these methods can be declared static which is a useful signal to the compiler as well as a signal to users of the methods should they be declared public rather than private. You will learn more about these qualifiers as we progress on the learning curve.
Any applet has to be invoked from an HTML document, which may provide a complete web page and in fact display many applets. For this exercise we have provided a minimal HTML document, the HTML file GoBanner1.html , which we will refer to as the HTML startup.
In this document, is a snippet of text which looks as follows:
<APPLET CODE="Banner1.class" WIDTH="390" HEIGHT="114" ALIGN="MIDDLE" ALT="( With a java enabled browser you would see animation here)"> </APPLET>
The entry CODE="Banner1.class" gives the connection to the applet, in this case, when the HTML startup and the byte code are in the same directory. If they should be in different directories the reference works if you give a full path from the directory of the HTML startup to the directory of the byte code.
The entries WIDTH="390" HEIGHT="114" ALIGN="MIDDLE" give the height and width of the window where the applet is to execute.
In exercise 1, we actually have two versions of GoBanner1.html, one which is used to demonstrate Banner1 in the folder EX1, but also another version whith the same name (did not have to be same name, but they do almost the same thing -- so what the heck) in the folder MyEX1. The difference is in the text outside the applet tag. In the EX1 version we provide a clickable reference to the source code document. Since the reference is to a document in the same level of the file hierarcy, the reference is direct. In the MyEX1 a reference to the source document would be to one level up in the file hierarchy and so we decided to eliminate the reference all together. It also explains why you could not just copy the startup HTML document from on level to another. If you did, the startup would function OK in the appletvieweer. It would also start up the applet in a webbrowser. However, when you would click on the link to the sourcecode document, you would get the "no such page found" error page.