MODULE 6p - Applets - Trials A
Here is the source of the simplest possible applet. Key this into the
file AppletA.java
import java.applet.Applet;
public class AppletA extends Applet
{ // No data fields
// No methods
}
Now compile it using the javac command:
$ javac AppletA.java
As a class with no data fields and no methods, AppletA cannot be expected
to do very much, but notice that it extends class Applet. This latter
class is not in the main Java package (java.lang) and an import statement
is required to import the class from the java.applet package as shown.
By extending class Applet, class AppletA inherits the data fields and
methods not only of Applet but of all the ancestors of Applet right back
to the root class Object. By way of interest the line of succession is:
Object - Component - Container - Panel - Applet - AppletA
Applets don't incorporate a method main() and are not run by using the
java command. Applets are intended to be run from Web browsers and it is
necessary to write some HTML. Key this source into the file AppletA.html
<HTML>
<BODY>
<APPLET code="AppletA.class" width=300 height=100>
Java is not available.
</APPLET>
</BODY>
</HTML>
Web browsers are still rather sluggish when processing applets and many
cannot cope with applets at all. The APPLET tag in the HTML specifies
(after code=) the name of the class file in quotes and specifies the
width and height in pixels. If the browser cannot process the applet
the message Java is not available will be displayed.
To test an applet it is best to use the appletviewer command:
$ appletviewer AppletA.html &
In outline, the sequence of events initiated by this command are:
1. The appletviewer program is loaded and starts running.
2. The program notes AppletA.html as the command line argument
and looks at the contents of this file. It sees the APPLET tag.
3. Given the information in the APPLET tag the appletviewer sets up
an applet window. This is divided horizontally into four regions:
+---------------------------+
Title bar | |
+---------------------------+
Menu bar | |
+---------------------------+
| |
| |
300x100 | |
region | |
| |
| |
+---------------------------+
Status bar | |
+---------------------------+
The title bar announces: Applet Viewer: AppletA.class
The menu bar has a single menu: Applet
The central region is 300 pixels wide and 100 pixels high
The status line at the bottom says: Applet started.
NB: the window is 300 pixels wide but more than 100 pixels high.
4. Next, the appletviewer program instantiates an AppletA object.
5. The appletviewer program then sees that no methods have been
specified in class AppletA and hangs up.
DATA FIELDS
By the principle of data hiding or encapsulation, the identifiers of most
of the data fields inherited by AppletA are not published but one can guess
at their presence and suggest names for some of them. Here are a few:
1. size - gives the size of the applet (both width and height
in pixels).
2. background - is the background colour (`color' in American).
3. graphics - provides a reference to the central region enabling
lines and shapes to be drawn on it.
4. layout - specifies how any items (or `charges', see 5) such as
buttons, checkboxes and labels are to be laid out.
5. charges - lists the items like buttons, checkboxes and labels
which are laid out on the applet. (The term `charge'
is unaccountably not found in Java textbooks. It is
taken from heraldry where items laid out on shields,
like lions and chevrons, are referred to as charges.)
6. listeners - lists any special objects set up to spring into action
when, for example, the mouse is clicked or the applet
loses focus.
Even this frivolous first applet has a size and a background colour but,
since no items have been laid out and no listeners have been set up, the
layout is irrelevant and charges and listeners will be empty lists.
METHODS
Of all the methods that are inherited by ANY class that extends Applet,
the five most important are:
init() start() paint() stop() destroy()
Any or all of these methods can be overridden to do useful things but the
inherited default versions do nothing.
Other important inherited methods are:
add() - used for adding an item to the list of charges.
add???Listener() - used for adding a listener to the list of listeners.
[Various possibilities can stand in the place of ???,
and addMouseListener() provides an example.]
EXPERIMENTS WITH THE FRIVOLOUS APPLET
1. Open the Applet menu. Select the Stop entry.
The status bar announces Applet stopped.
2. Select the Start entry on the menu.
The status bar announces Applet started.
3. Select the Restart entry on the menu.
This is supposed to be equivalent to (2) followed by (3) and the
status bar again concludes with Applet started.
4. Select the Quit entry on the menu.
This is how to finish with an applet.
A FIRST VARIATION
Modify the source code in AppletA.java so that it appears thus:
import java.applet.Applet;
import java.awt.Graphics;
public class AppletA extends Applet
{ private String s = "Greetings";
public void paint(Graphics g)
{ g.drawString(this.s, 100, 60);
}
}
Compile it using the javac command:
$ javac AppletA.java
A second import statement is required for the class Graphics which is
in the java.awt package. This class is required since it is the type
of the argument of the paint() method.
This version of AppletA includes a data field and a method. The data
field s augments the inherited data fields and the method paint()
overrides the inherited paint() method.
The data field is of type String and is initialised to "Greetings".
The method paint() causes "Greetings" to be drawn on the central region.
The explanation can wait a moment. First, using the same HTML as before,
run the appletviewer program on this new applet:
$ appletviewer AppletA.html &
The appearance of the applet window is just as before except that the
String "Greetings" has been drawn roughly in the middle.
This time, after instantiating an AppletA object, the appletviewer
program invokes the paint() method which requires an argument. The
actual argument handed over by the appletviewer program is the object
referred to by the (inherited) data field graphics which provides a
reference to the central region of the applet window.
The formal argument g then has access to all the methods of this
object and these include drawString() which draws a string in the
central region. This method is invoked by the statement:
g.drawString(this.s, 100, 60);
The first argument of drawString is the String to be drawn (here this.s
refers to "Greetings"). The second two arguments show the position of the
start of the string relative to the top left-hand corner of the central
region. Thus the string begins 100 pixels to the right of and 60 pixels
below the top left-hand corner.
After invoking the paint method, the running program hangs up.
EXPERIMENTS WITH THE NEW APPLET
Repeat the previous experiments. Little has changed except that when the
Stop entry on the menu is selected not only does the status bar reflect
Applet stopped but the drawn String disappears too. On selecting Start
it reappears.
Select the Quit entry in the menu to finish with the applet.
A SECOND VARIATION
It has been noted that five important methods in ANY applet are:
init() start() paint() stop() destroy()
Each of these methods is invoked from the appletviewer and, for each, there
are well-defined moments for being invoked.
For example, the stop() method is invoked when the Stop entry in the menu
is selected. Obviously the appletviewer cannot invoke a method which doesn't
exist so stop() (and the others) are mandatory in any applet. If the user
doesn't supply overriding versions then the inherited versions will be
invoked. These are guaranteed to do nothing.
In the final version of AppletA, overriding versions of all five methods are
supplied. Each contains a println() statement so that a log will be built up
showing just when each method is invoked.
Modify the source code in AppletA.java again so that it appears thus:
import java.applet.Applet;
import java.awt.Graphics;
public class AppletA extends Applet
{ private String s = "Greetings";
public void init()
{ System.out.println("Done init");
}
public void start()
{ System.out.println("Done start");
}
public void paint(Graphics g)
{ g.drawRect(15, 15, 270, 70);
g.drawString(this.s, 100, 60);
System.out.println("Done paint");
}
public void stop()
{ System.out.println("Done stop");
}
public void destroy()
{ System.out.println("Done destroy");
}
}
One other augmentation is the extra statement in the paint() method:
g.drawRect(15, 15, 270, 70);
This draws a rectangle whose top left-hand corner is 15 pixels to the
right of and 15 pixels below the top left-hand corner of the central
region and, further, the rectangle is 270 pixels wide and 70 high.
Recall that the central region is 300 pixels wide and 100 pixels high
and note that 15 + 270 + 15 = 300 and 15 + 70 + 15 = 100 so the
rectangle is roughly centred in the available space.
Again use javac to compile the applet:
$ javac AppletA.java
Now give the command:
$ appletviewer AppletA.html &
The only difference in the appearance of the applet window now is the
enveloping rectangle but, separately, the first three lines of the log
appear after the appletviewer command.
WHAT HAPPENS AND WHEN
After the applet window is set up, the following sequence of events
occurs:
1. The appletviewer instantiates the AppletA object. In effect there
is the statement:
AppletA handle = new AppletA();
The identifier handle enables the appletviewer to access the data
fields and methods in the applet. For example handle.graphics
(see footnote below) enables the appletviewer to use the reference
to the central region and handle.init() enables the appletviewer
to invoke the init() method.
2. Shortly after instantiating the AppletA object, the appletviewer
invokes:
handle.init();
This results in Done init being printed in the log.
3. Next the appletviewer invokes:
handle.start();
This results in Done start being printed in the log.
4. Next the appletviewer invokes:
handle.paint(handle.graphics);
The actual argument handle.graphics is handed over to the formal
argument g of the paint() method. The body of the paint() method
draws the enveloping rectangle and then draws the String.
The third statement in the body of paint() results in Done paint
being printed in the log (possibly more than once as explained later).
5. The appletviewer then hangs up but...
Now select Reload in the applet menu...
6. This causes the appletviewer to close the applet and reload it.
The closing process involves two stages, first:
handle.stop();
This results in Done stop being printed in the log and the status bar
also records Applet stopped. The second stage in the closing process
is:
handle.destroy();
This results in Done destroy being printed in the log and any resources
used by the applet are then freed.
7. If Quit had been selected instead of Reload this would be the end
of the story. With Reload there is a fresh beginning and the
appletviewer invokes handle.init() handle.start() and then
handle.paint(handle.graphics) and again hangs up.
The messages Done init Done start Done paint are printed once
again. As before Done paint may be printed more than once. An
explanation is provided in the section following the footnote.
FOOTNOTE ABOUT handle.graphics
The data field graphics was introduced as a hypothesis; this is a suggested
identifier for something that isn't published. Although its proper identifier
is unknown its value can be obtained by using the method getGraphics() and
this method IS published. Accordingly, the actual argument passed to paint()
by the appletviewer is handle.getGraphics() rather than handle.graphics
For simplicity, handle.paint(handle.graphics) is used in this introduction
to applets rather than handle.paint(handle.getGraphics()) which is more
likely to be the truth.
THE FIVE PRINCIPAL METHODS
The five methods are invoked by the appletviewer program at well-defined
moments. Roughly speaking:
init() is invoked on initial entry (or after reloading) and is
intended for once-and-for-all-setting-up statements.
start() is invoked after init() (or after restarting) and is
intended for statements which follow initialisation but
come before paint() is invoked.
paint() is invoked after init() and start() but also whenever
any repair work is required to the central region. Most
obviously it is invoked after part (or all) of the region
has been obscured and revealed again or after the applet
window has been resized. Accordingly, paint() is typically
invoked more frequently than the other methods.
stop() is invoked after selecting Stop in the Applet menu. It
is also invoked when Quit is selected [in which case
destroy() follows immediately].
destroy() is invoked on selecting Quit.
Some experiments will illuminate the processes further.
EXPERIMENTS AND OBSERVATIONS
When conducting the following experiments keep an eye on the log check which
method is being invoked and in which circumstances.
1. Cover up part of the applet window and then reveal it again.
All the pixels are restored. Whenever such restoration is needed,
handle.paint() is automatically invoked.
2. Change the size of the applet window.
This too causes handle.paint() to be invoked, possibly twice.
3. Select the Stop entry.
This invokes handle.stop() and the central region is cleared.
4. Select the Start entry on the menu.
This invokes handle.start() and then handle.paint(handle.graphics)
to restore the central region.
5. Iconify the applet window.
Besides iconifying the window this is equivalent to selecting Stop
and handle.stop() is invoked.
6. Deiconify the icon.
Besides deiconifying the window this is equivalent to selecting
Start and handle.start() and handle.paint(handle.graphics) are
invoked in turn.
7. Select the Reload entry on the menu.
As explained before, the appletviewer invokes handle.stop() and
handle.destroy() and then there is a fresh beginning. The methods
handle.init() handle.start() and handle.paint(handle.graphics)
are invoked in turn.
Accordingly, five messages are printed.
8. Select the Restart entry on the menu.
This is supposed to be equivalent to Stop followed by Start but
with some versions of appletviewer there is a bug and Restart is
exactly the same as Reload. Check the messages carefully.
9. Select the Quit entry in the menu.
The appletviewer invokes handle.stop() and handle.destroy() and
removes the applet window altogether.