Here Here Here: Java Applet Tutorial
Here Here Here: Java Applet Tutorial
This site is meant to be a quick-and-dirty introduction to writing Java applets. A set of example
applets are given to be used as exercises. Feel free to download the source code herein, try it out on
your own machine, and modify it.
Designers and artists: this tutorial emphasizes visual and interactive aspects of applets. It was
made especially for people wishing to create small, graphical, expressive forms with Java.
However, if you have no programming experience at all, you'll probably need additional learning
resources. Please see the note below for first-time programmers.
Before getting started, you'll need a compiler for Java, so that you can translate source code into
something executable. You could, for example, download Sun's Java Software Development Kit
(abbreviated as JDK or SDK), which includes a compiler, utilities, example applets, and a boat-load
of documentation. (Mac users can try here, here and here.) Be sure to get the Java SDK and not the
JRE (Java Runtime Environment) -- the former allows you to compile java programs, the latter only
allows you to run them.
After getting a compiler, you can try out the examples. The first one, "Drawing Lines", walks you
through the process of creating an applet. Please note that lessons 9-12 are unfinished, as I have yet
to get around to completing them.
1 Drawing Lines
2 Drawing Other Stuff
3 Color - introduces arrays
4 Mouse Input - introduces showStatus( ) and Vector
5 Keyboard Input
6 Threads and Animation - introduces System.out.println( )
Backbuffers - introduces Math.random( ) and
7
Graphics.drawImage( )
8 Painting
9 Clocks
10 Playing with Text - introduces 2D arrays and hyperlinks
11 3D Graphics - introduces classes
12 Odds and Ends
All of these examples were designed to be small and, hopefully, easy to absorb. If you couldn't find
information here that you need, you might try Sun's website, which has copious documentation on
Java, along with online tutorials and examples. You might also try the Java FAQ, a copy of which
can be found by searching for "java faq" in any good search engine (or just try here -- the same site
also hosts a tutorial).
If you're looking for books on Java, O'Reilly publishes some good ones, although they are most
useful to people with at least a bit of prior programming experience. Java in a Nutshell by David
Flanagan (in its 3rd edition, at the time of writing) covers the basic features of Java, including the
syntax of the language, data structures, object-oriented features, and threads. Determined novices
with no programming experience may find it useful. Java Foundation Classes in a Nutshell by
David Flanagan describes how to create GUIs with widgets and how to draw basic graphics, among
other things. Java 2D Graphicsby Jonathan Knudsen, also published by O'Reilly, discusses in
detail the graphics features of the Java 2 platform.
First-time programmers will probably find that the explanations given in this tutorial are too brief
and leave out too many details. Basic information on the Java language can be found here (try to
focus on understanding the syntax of variables, expressions, loops, and flow control structures at
first -- we hardly make use of any object-oriented concepts in this tutorial). There are some books
on Java for first-time programmers: this site recommends Java: An Introduction to Computer
Science and Programming by Walter Savitch et al., Problem Solving With Java by Elliot B.
Koffman and Ursula Wolz, andIntroduction to Programming Using Java: An Object-Oriented
Approach by David M. Arnow and Gerald Weiss. You might also try getting a feel for some basic
programming concepts by learning a simpler language first, such as DBN.
Terminology : Note that the term function is used in this tutorial in place of the more modern (and
object-oriented) term method.
Now, you have to compile the source code to generate a bytecode file called DrawingLines.class. If
you're using Sun's Java Software Development Kit, you can compile by typing javac
DrawingLines.java at a command prompt (on Windows, this is done within an MS-DOS shell).
Check that the .class file was indeed generated.
(If the .html file is not in the same directory as the .class file, you'll have to add
a codebase="..." attribute specifying the path to the class file. More information on
the <applet> tag can be found here.) When you view the .html file in a web browser, you should
see something like this:
Here's a second version of the same source code, this time with comments:
import java.applet.*;
import java.awt.*;
// Store the height and width of the applet for future reference.
width = getSize().width;
height = getSize().height;
g.setColor( Color.red );
g.drawRect( 10, 20, 100, 15 );
g.setColor( Color.pink );
g.fillRect( 240, 160, 40, 110 );
g.setColor( Color.blue );
g.drawOval( 50, 225, 100, 50 );
g.setColor( Color.orange );
g.fillOval( 225, 37, 50, 25 );
g.setColor( Color.yellow );
g.drawArc( 10, 110, 80, 80, 90, 180 );
g.setColor( Color.cyan );
g.fillArc( 140, 40, 120, 120, 90, 45 );
g.setColor( Color.magenta );
g.fillArc( 150, 150, 100, 100, 90, 90 );
g.setColor( Color.black );
g.fillArc( 160, 160, 80, 80, 90, 90 );
g.setColor( Color.green );
g.drawString( "Groovy!", 50, 150 );
}
}
For documentation on the Graphics class and the parameters that are passed to functions such
as drawRect(), fillOval(), etc., go here.
Please note that some of the member functions in Graphics, such as fillRect(), interpret
the width and height parameters as measured between pixel edges; hence the resulting figure will
truly be widthpixels wide and height pixels high. However, other functions, such as drawRect(),
assume dimensions are measured between pixel centres; hence the resulting figure will actually
be width+1 by height+1pixels.
Exercise 3: Color
// As i goes from 1 to N, this color goes from almost pure green to pure red.
spectrum2[ i-1 ] = new Color( i/(float)N, (N-i)/(float)N, 0 );
}
}
int step = 90 / N;
for ( int i = 0; i < N; ++i ) {
g.setColor( spectrum[ i ] );
g.fillArc( 0, 0, 2*width, 2*height, 90+i*step, step+1 );
g.setColor( spectrum2[ i ] );
g.fillArc( width/3, height/3, 4*width/3, 4*height/3, 90+i*step, step+1 );
}
}
}
A second example:
import java.applet.*;
import java.awt.*;
import java.lang.Math;
g.setColor( spectrum[ i ] );
g.drawString( "Color", width/2+x, height/2+y );
}
}
}
The output:
mx = width/2;
my = height/2;
addMouseListener( this );
addMouseMotionListener( this );
}
Try clicking and dragging on the resulting applet. Notice how the status bar in your web browser
displays the current mouse position -- that's due to the calls to showStatus(). (You might see some
occasional flickering in this applet. This problem will be addressed in an upcoming lesson.)
Another example:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
x = width/2 - 20;
y = height/2 - 20;
addMouseListener( this );
addMouseMotionListener( this );
}
// displace the box by the distance the mouse moved since the last event
// Note that "x += ...;" is just shorthand for "x = x + ...;"
x += new_mx - mx;
y += new_my - my;
repaint();
e.consume();
}
}
A third example:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
addMouseListener( this );
addMouseMotionListener( this );
}
if ( listOfPositions.size() >= 50 ) {
// delete the first element in the list
listOfPositions.removeElementAt( 0 );
}
repaint();
e.consume();
}
public void mouseDragged( MouseEvent e ) { }
Move freely over the applet. Notice that moving faster makes the line stretch out longer.
x = width/2;
y = height/2;
addKeyListener( this );
addMouseListener( this );
}
Try clicking and typing into the applet. You'll probably have to click at least once before you begin
typing, to give the applet the keyboard focus.
Here's a second applet that nicely integrates most of what we've learned so far.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
addKeyListener( this );
addMouseListener( this );
addMouseMotionListener( this );
}
if ( listOfPositions.size() >= N ) {
// delete the first element in the list
listOfPositions.removeElementAt( 0 );
}
repaint();
e.consume();
}
public void mouseDragged( MouseEvent e ) { }
Click, type, and move the mouse. You might see some flickering. Depending on the speed of your
computer, you might also find that the mouse position is being sampled too quickly or too slowly.
The upcoming lessons will give you tools to fix both of these problems.
The only functions we have seen in applets so far are init(), paint(), and functions called in
response to input events. All of these functions are supposed to do a small amount of work and
return quickly. There has been no opportunity, so far, for a function to loop and do some
continuous work.
This applet creates a thread, a separate stream of execution, to perform a background task. The
body of the thread's code is in the run() function. In this case, the purpose of the thread is to
increment the variable i once every 1000 milliseconds, and cause the applet to redraw itself. The
result is a simple animation.
import java.applet.*;
import java.awt.*;
// Executed whenever the browser leaves the page containing the applet.
public void stop() {
System.out.println("stop(): begin");
threadSuspended = true;
}
// Executed within the thread that this applet created.
public void run() {
System.out.println("run(): begin");
try {
while (true) {
System.out.println("run(): awake");
The call to showStatus() in run() will cause the value of i to appear in the browser's status bar. If
you open the Java Console of your browser (in Netscape 4.7, this is accessible under the
Communicator|Tools submenu), you'll see the text printed by calls to System.out.println().
Unfortunately, the source code is complicated because the applet is supposed to suspend execution
of the thread whenever the browser leaves the web page containing the applet, and resume
execution upon return. This is done in the stop() and start() functions, respectively. Basically, the
thread monitors the value of some variable, here called threadSuspended, that behaves like a flag.
When the thread sees that it is supposed to suspend itself, it calls wait(), which blocks the thread
and does not allow it to continue executing until the applet calls notify().
Strictly speaking, it is not necessary to suspend the thread at all, but failing to do so is somewhat
irresponsible. The user's CPU could become bogged down with useless instructions to execute long
after the browser has left the page containing the applet. Those tempted to forgo "proper" coding to
make their applets simpler can use this as an example. When you run this applet, open the Java
Console of your browser, and then leave the page the applet is on. Notice how messages continue
to be printed out in the console, and the value of i continues to be displayed in the status bar,
demonstrating that the thread is still running in the background.
Exercise 7: Backbuffers
Up to this point, the graphics drawn by our applets have been relatively simple. With more complex
graphics however, whether in animations or interactive programs, flicker can become a problem.
(You may have already noticed subtle flickering in some of the previous applets.)
This example demonstrate the problem. It uses a pseudo-random number generator to produce a
big, hairy tangle of lines. The lines follow the mouse cursor.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
mx = width/2;
my = height/2;
addMouseMotionListener( this );
}
The output:
You probably see flickering when you move the mouse over the applet. The lines take a significant
amount of time to draw, and since the canvas is cleared before each redraw, the image on the
canvas is actually incomplete most of the time.
This second example makes the problem even more pronounced by rendering a bitmap image in the
background.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
mx = width/2;
my = height/2;
addMouseMotionListener( this );
}
public void mouseMoved( MouseEvent e ) {
mx = e.getX();
my = e.getY();
showStatus( "Mouse at (" + mx + "," + my + ")" );
repaint();
e.consume();
}
public void mouseDragged( MouseEvent e ) { }
The output:
The solution is to use double-buffering : rather than perform drawing operations directly to screen,
we draw onto an image buffer (the "backbuffer") in memory, and only after completing this image
do we copy it onto the screen. There is no need to erase or clear the contents of the screen before
copying (or "swapping", as it's called) the backbuffer onto the screen. During the swap, we simply
overwrite the image on the screen. Hence the screen never displays a partial image: even in the
middle of swapping, the screen will contain 50 % of the old image and 50 % of the new image. As
long as the swap is not too slow, the eye is fooled into seeing a continuous, smooth flow of images.
mx = width/2;
my = height/2;
addMouseMotionListener( this );
}
repaint();
e.consume();
}
public void mouseDragged( MouseEvent e ) { }
The output:
Why do we still see flicker ? Whenever the applet is supposed to redraw itself, the
applet's update() function gets called. The java.awt.Component class (which is a base class
of Applet) defines a default version of update() which does the following: (1) clears the applet by
filling it with the background color, (2) sets the color of the graphics context to be the applet's
foreground color, (3) calls the applet'spaint() function. We see flickering because the canvas is still
cleared before each redraw. To prevent this, we need to define our own update() function, to
override the base class' behavior.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
mx = width/2;
my = height/2;
addMouseMotionListener( this );
}
repaint();
e.consume();
}
public void mouseDragged( MouseEvent e ) { }
Update (January 2008): I received the following email message that might be useful to some
readers.
Hello,
anyways
thank you for your work
Artur Wielogórski
(student @Poznan University of Technology)
Exercise 8: Painting
In addition to reducing flicker, a backbuffer can be used to store the accumulated results of drawing
operations. We can easily implement a canvas-and-brush applet:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
addMouseMotionListener( this );
}
Another example:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
x = width/2;
y = height/2;
addKeyListener( this );
addMouseListener( this );
}
A third example:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
double t = 0;
mx = width / 2;
my = height / 2;
addMouseMotionListener( this );
}
Programming a custom brush and canvas enables experimentation with behaviors not otherwise
possible. An understanding of arithmetic, geometry, and trigonometry will enhance your own
ability to "play" in this medium.
Exercise 9: Clocks
SimpleDateFormat formatter
= new SimpleDateFormat( "hh:mm:ss", Locale.getDefault() );
Date date = cal.getTime();
timeString = formatter.format( date );
Note that the time displayed in the lower left corner may not be correct -- certain browsers (perhaps
only older versions?) seem to interpret the "default" time zone as something different from the local
time zone. (The hands, however, always seem to display the correct time.) If this problem bothers
you, try using
timeString = date.toString();
instead of
timeString = formatter.format( date );
Graphics g;
g.setFont( font );
String s = "whatever";
int stringWidth = fm.stringWidth( s );
class Point3D {
public int x, y, z;
public Point3D( int X, int Y, int Z ) {
x = X; y = Y; z = Z;
}
}
class Edge {
public int a, b;
public Edge( int A, int B ) {
a = A; b = B;
}
}
Image backbuffer;
Graphics backg;
Point3D[] vertices;
Edge[] edges;
addMouseListener( this );
addMouseMotionListener( this );
}
repaint();
e.consume();
}
Notice that the compiler generates 3 .class files: one for each of the classes defined.
Audio
To play audio files, use Applet.play(). Java 1.1 only supports Sun Audio (.au) files, or
specifically, 8 bit, u-law, 8000 Hz, one-channel Sun
format. Both Applet.play() and AudioClip.play() are non-blocking: they return immediately after
starting the playback of the audio file. Try here for an example.
Applet Info
Debugging Tips
If you're having trouble understanding what your applet is doing (or not doing),
use System.out.println() and showStatus() to print out the values of variables and information
about where the program is.
Browsers won't normally reload applets after they've been loaded once. If you test an applet inside
your browser, and then modify the applet's source code and recompile, simply reloading the
webpage in your browser isn't enough to view the new applet. You'll have to exit and restart your
browser. To avoid this nuisance, do initial testing of applets with appletviewer rather than a web
browser.
Conditional Compilation
Java is not as flexible, but allows for something that is sometimes just as good:
private static final boolean DEBUG = false;
...
if ( DEBUG ) {
...
}
else {
...
}
The final keyword means the variable is constant, so unless your compiler's optimizer is brain-
dead, it should prune out the conditional and the unreachable block of code.
import java.applet.*;
import java.awt.*;
import java.lang.Math;
width = getSize().width;
height = getSize().height;
setBackground( Color.black );
setForeground( Color.green );
}