Java Tutorials Part-2

Applets

The last chapter was rooted solidly in the 1970's. It used techniques often referred to as "structured" or "procedural programming" which were popular then. (We skipped right over the most popular innovation of the 60's and the Basic programmer, spaghetti code). Certain programmers are sometimes said to "Write Fortran in any language," and that's more or less what we did. You now have the knowledge to accomplish with Java anything that can be done within the bounds of ANSI-standard Fortran 77.

In this chapter we're going to move into the 1980's. In particular we're going to work with event driven programming. This style of programming should be very familiar to Macintosh and Windows programmers. In those environments program logic doesn't flow from the top to the bottom of the program as it does in most procedural code. Rather the operating system collects events and the program responds to them. These events may be mouse clicks, keypresses, network data arriving on the Ethernet port, or any of about two dozen other possibilities. The operating system looks at each event, determines what program it was intended for, and places the event in the appropriate program's event queue.

Every application program has an event loop. This is just a while loop which loops continuously. On every pass through the loop the application retrieves the next event from its event queue and responds accordingly.

Java applets behave similarly. However the runtime environment (i.e. the browser) takes care of the event loop for the applet so there's no need to write one explicitly. Rather you need to have methods in your applet subclass that respond to each kind of event you want to process.

This is all fairly abstract until you see some concrete examples. Let's begin with a simple one.

Hello World: The Applet

The reason people are excited about Java as more than just another OOP language is because it allows them to write interactive applets on the web. Hello World isn't a very interactive program, but let's look at a webbed version.

import java.applet.Applet;

import java.awt.Graphics;

public class HelloWorldApplet extends Applet {

public void paint(Graphics g) {
g.drawString("Hello world!", 50, 25);
}
}
This applet version of HelloWorld is a little more complicated than the HelloWorld application of the previous chapter, and it will take a little more effort to run it as well.

First type in the source code and save it into file called HelloWorldApplet.java in the javahtml/classes directory. Compile this file by typing javac HelloWorldApplet.java at the command line prompt.

If all is well a file called HelloWorldApplet.class will be created. This file must be in your classes directory.

Now you need to create an HTML file that will include your applet.

APPLET codebase="classes" code="HelloWorldApplet.class" width=200 height=200

Save this file as "HelloWorldApplet.html" in the javahtml directory. When you've done that load the HTML file into a Java enabled browser such as HotJava or Netscape 2.0. You should see the following:
This is the applet:
Hello World!

If the applet compiled without error and produced a HelloWorldApplet.class file, and yet you don't see the string "Hello World" in your browser chances are that the class file is in the wrong place. Make sure the .html file is in the javahtml directory and the compiled .class file is in the javahtml/classes directory.
Examining the Hello World Applet

The Hello World Applet adds several constructs to what we saw in the Hello World Application. Moving from top to bottom the first thing you notice is the two lines:
import java.applet.Applet;
import java.awt.Graphics;

The import statement in Java is similar to the #include statement in C or C++. It pulls in the classes that are contained in a package elsewhere. A package is merely a collection of related classes. In this case we're requesting access to the public classes contained in the basic release, java.applet.Applet and java.awt.Graphics. Depending on the phase of the moon, awt stands for "advanced window toolkit" or "applet window toolkit". You'll see a lot more of it.

The next change from the application is the Class definition:

public class HelloWorldApplet extends Applet

The extends keyword indicates that this class is a subclass of the Applet class; or, to put it another way, Applet is a superclass of HelloWorldApplet. The Applet class is defined in the java.applet.Applet package which we just imported. Since HelloWorldApplet is a subclass of the Applet class, our HelloWorldApplet automatically inherits all the functionality of the generic Applet class. Anything an Applet can do, the HelloWorldApplet can do too.

The next difference between the applet and the application is far less obvious (except maybe to a longtime C programmer). There's no main method! Applets don't need them. The main method is actually in the browser or the AppletViewer, not in the Applet itself. Applets are like plugin code modules for Adobe Photoshop that provide extra functionality, but can't run without a main program to host them.

Rather than starting at a specific place in the code applets are event driven. An applet waits for one of a series of events such as a key press, the mouse pointer being moved over the applets visible area, or a mouse click and then executes the appropriate event handler. Since this is our first program we only have one event handler, paint.

Most applets need to handle the paint event. This event occurs whenever a part of the applet's visible area is uncovered and needs to be drawn again.

The paint method is passed a Graphics object which we've chosen to call g. The Graphics class is defined in the java.awt.Graphics package which we've imported. Within the paint method we call g's drawString method to draw the string "Hello World!" at the coordinates (50,25). That's 50 pixels across and twenty-five pixels down from the upper left hand corner of the applet. We'll talk more about coordinate systems later. This drawing takes place whenever a portion of the screen containing our applet is covered and then uncovered and needs to be refreshed.

The APPLET HTML Tag
Applets are included on web pages using the <> tag. The APPLET tag is perhaps most similar to the tag. Like needs to reference a source file that is not part of the HTML page on which it is embedded. IMG's do this with the SRC= parameter. APPLET's do this with the CODE= parameter. The CODE parameter tells the browser where to look for the compiled .class file. It is relative to the location of the source document. Thus if you're browsing http://metalab.unc.edu/javafaq/index.html and that page references an applet with CODE=animation.class, then the animation.class file needs to be at http://metalab.unc.edu/javafaq/animation.class.

For reasons that remain a mystery to HTML authors everywhere, but possibly having something to do with packages and classpaths, if the applet resides somewhere other than the same directory as the page it lives on, then you don't just give a URL to its location. Rather you point at the directory where the .class file is using the CODEBASE parameter. You still also have to use CODE to give name of the .class file.

Also like IMG, APPLET has several parameters to define how it is positioned on the page. HEIGHT and WIDTH parameters work exactly as they do with IMG, specifying how big a rectangle the browser should leave for the applet. These numbers are specified in pixels. ALIGN also works exactly as for images (in those browsers that support ALIGN) defining how the applet's rectangle is placed on the page relative to other elements. Possible values include LEFT, RIGHT, TOP, TEXTTOP, MIDDLE, ABSMIDDLE, BASELINE, BOTTOM and ABSBOTTOM. Finally as with IMG you can specify an HSPACE and a VSPACE in pixels to set the amount of blank space between an applet and the surrounding text.

Finally also like IMG, APPLET has an ALT tag. As far as I know ALT is not yet implemented in any browsers. An ALT tag is used by a browser that understands the APPLET tag but for some reason cannot play the applet. For instance if an applet needs to write a file on your hard drive, but your preferences are set not to allow that, then the browser should display the ALT text.

ALT is not used for browsers that do not understand APPLET at all. For that purpose APPLET has been defined to include a closing tag as well,
. All raw text between the opening and closing APPLET tags is ignored by a Java capable browser. However a non-Java capable browser will ignore the APPLET tags instead and read the text between them.
Passing Parameters to Applets

The area between the opening and closing APPLET tag is also used to pass parameters to applets. This is done through the use of the PARAM HTML tag and the getParameter method of the java.applet.Applet class.

To demonstrate this we'll convert HelloWorldApplet into a generic string drawing applet. To do this we'll need to pass the applet parameters that define the string to be drawn.
import java.applet.Applet;
import java.awt.Graphics;
public class DrawStringApplet extends Applet {

String input_from_page;

public void init() {
input_from_page = getParameter("String");
}
public void paint(Graphics g) {
g.drawString(input_from_page, 50, 25);
}
}
Now you need to create an HTML file that will include your applet.

This is the applet:
APPLET codebase="classes" code="DrawStringApplet.class" width=200 height=200>
Of course you are free to change "Howdy, there!" to a string of your choice. Note that this allows you to change the output of the applet without changing or recompiling the code.

You're not limited to one parameter either. You can pass as many named parameters to an applet as you like.

The getParameter method is straightforward. You give it a string that's the name of the parameter you want. You get back a string that's the value of the parameter. All parameters are passed as Strings. If you want to get something else like an integer then you'll need to pass it as a String and convert it into the type you really want.

The PARAM HTML tag is also straightforward. It occurs between and . It has two parameters of its own, NAME and VALUE. The NAME identifies which parameter this is for the getParameter method. VALUE is the value of the parameter as a String. Both must be enclosed in double quote marks like all other HTML tag parameters.

Events and Applets
Event Tutor Applet
The following applet is designed to give you some feel for just what event driven programming is like and what the various events you're likely to encounter are. Whenever an event occurs, the applet responds by printing the name of the event at the command line.
import java.applet.Applet;
import java.awt.*;
public class EventTutor extends Applet {

public void init() {
System.out.println("init event");
}
public void paint(Graphics g) {
System.out.println("paint event");
}
public void start() {
System.out.println("start event");
}
public void destroy() {
System.out.println("destroy event");
}
public void update(Graphics g) {
System.out.println("update event");
}
public boolean mouseUp(Event e, int x, int y) {
System.out.println("mouseUp event");
return false;
}
public boolean mouseDown(Event e, int x, int y) {
System.out.println("mouseDown event");
return false;
}
public boolean mouseDrag(Event e, int x, int y) {
System.out.println("mouseDrag event");
return false;
}
public boolean mouseMove(Event e, int x, int y) {
System.out.println("mouseMove event");
return false;
}
public boolean mouseEnter(Event e, int x, int y) {
System.out.println("mouseEnter event");
return false;
}
public boolean mouseExit(Event e, int x, int y) {
System.out.println("mouseExit event");
return false;
}
public void getFocus() {
System.out.println("getFocus event");
}
public void gotFocus() {
System.out.println("gotFocus event");
}
public void lostFocus() {
System.out.println("lostFocus event");
}
public boolean keyDown(Event e, int x) {
System.out.println("keyDown event");
return true;
}
}
Once you've compiled and loaded this applet play with it. Click the mouse in the applet window. Doubleclick the mouse. Click and drag. Type some text. Resize the browser window. Cover it and then uncover it. Keep your eye on the standard output (Java console in Netscape) while doing this.

Here are some questions to answer:

Can you have a mouseDown event that is not followed by a mouseUp event?
Can you have a mouseDown event that is not followed by a mouseDrag event?
Can you have a mouseUp Event that is not preceded by a mouseDown event?
What has to happen for a paint event to occur?
What's the most common event? Why?
Are there any events you don't see?
How many times can you make the start event get called? the stop event?
Of those events you can make occur, exactly how do you do it? How many different ways can you do it? There are a number of new things in this code but none of them are particularly difficult. The first one is the second import statement, import java.awt.*. This time we need more than one class from the awt package so rather than worrying about which one to import, we just get them all with the *. The compiler is smart enough to only link in those that it actually uses.

Finally there are a whole lot of new event methods. We'll cover them in detail in the next section. For now see under what circumstances you can make each one happen.
Making a List

It is extremely bad form to use System.out.println() in an applet. On some systems this may not work at all. However it has the advantage of being familiar and easy. For more serious work you should actually draw your text in the applet window. There are at least three different ways to do this. For our purposes the one that makes the most sense is to use a List.

A List is a scrolling list of Strings defined in java.awt.List. We create a new List with new, just as we create any other Object. The specific constructor we use asks for an int that's the number of visible lines and a boolean that tells whether or not multiple selections are allowed. We'll ask for 25 lines and no multiple selections.

List theList;
theList = new List(25, false);

We add Strings to the list by using the addItem method of the List we're adding to like so:

theList.addItem("This is a list item");

Finally we need to actually add this List to our applet (more precisely the applet's container). We do this with the line

add(theList);

in the init method. That's all. We can use the same applet we used before with these simple changes.
import java.applet.Applet;
import java.awt.*;
public class EventList extends Applet {

List theList;

public void init() {
theList = new List(25, false);
add(theList);
theList.addItem("init event");
}
public void paint(Graphics g) {
theList.addItem("paint event");
}
public void start() {
theList.addItem("start event");
}
public void destroy() {
theList.addItem("destroy event");
}
public void update(Graphics g) {
theList.addItem("update event");
}
public boolean mouseUp(Event e, int x, int y) {
theList.addItem("mouseUp event");
return false;
}
public boolean mouseDown(Event e, int x, int y) {
theList.addItem("mouseDown");
return false;
}
public boolean mouseDrag(Event e, int x, int y) {
theList.addItem("mouseDrag event");
return false;
}
public boolean mouseMove(Event e, int x, int y) {
theList.addItem("mouseMove event");
return false;
}
public boolean mouseEnter(Event e, int x, int y) {
theList.addItem("mouseEnter event");
return false;
}
public boolean mouseExit(Event e, int x, int y) {
theList.addItem("mouseExit event");
return false;
}
public void getFocus() {
theList.addItem("getFocus event");
}
public void gotFocus() {
theList.addItem("gotFocus event");
}
public void lostFocus() {
theList.addItem("lostFocus event");
}
public boolean keyDown(Event e, int x) {
theList.addItem("keyDown event");
return true;
}
}

We'll talk more about containers, Lists, and applet components in a later section.
The Events

In this section we're going to categorize the events your applet should respond to. You may not always need to respond to each one. For some of the events we'll also include new methods for the EventTutor applet that show a little more information. When we do you should replace the old method with the new one.

init
The init() method is called when your applet begins executing. Netscape is also known to call this method at other times such as when an applet is reloaded or you return to a page containing an applet. Generally you use this method to set up any data structures or perform any tasks you need to get ready to run the applet. Since it's only called once it's easy to miss the init() method in the EventTutor applet. If necessary redirect the standard output to a file and look at the first line of that file to see it.
public void init() {
System.out.println("init event");
}
paint
We've already seen the paint() method. Almost any applet is going to need to override this method. This is the method in which you will do all your drawing. You can only write to the applet screen in the paint method. However there are times when you'll want to write to an offscreen image in another method and then just quickly copy that image to the screen in your paint() method.

public void paint(Graphics g) {
theList.addItem("paint event");
}
stop
A stop() message says the user is no longer looking at the page that contains the applet. This is usually because the user left the page or minimized the window. At this time you should stop any CPU eating activities that don't matter when the user isn't looking at your page. For instance your Doom applet should stop tracking monster movement if the user isn't actually playing. On the other hand a spreadsheet applet in the middle of a long calculation should continue calculating because the user is likely to want the result later. Once the user returns to the page the start() method is called.

public void stop() {
theList.addItem("stop event");
}
start
The start() method is called when a user brings their attention back to an applet, for instance after maximizing a window or returning to the applet's page. It is called after the init() method. Initialization code that needs to be performed every time an applet is restarted should be put here.

public void start() {
theList.addItem("start event");
}
destroy
The destroy() method is called before the applet is unloaded completely. It is called after the stop() method. Users may reload the applet later, but if they do it will be as if they've never seen it before. All variables, static, member, local or otherwise will be initialized to their initial state. If you have any final cleanup to do (for instance sending output back to the httpd server) do it here.

public void destroy() {
theList.addItem("destroy event");
}
update
The update() method is called automatically by the system when ????. It's often overridden when you want to use offscreen Images to avoid flicker.

public void update(Graphics g) {
theList.addItem("update event");
}
mouseUp
The mouseUp() method is called whenever the mouse button is released in your applet. In most cases this is the event you'll want to watchout for, not mouseDown. A button is typically highlighted when the mouse button is pressed on it, but it is not activated till the user releases the mouse button. This gives the user a chance to change their mind by moving the cursor off the object without releasing it.

The exception would be when you want an action to continue as long as the mouse button is held down, a fast forward button on a movie playing applet for instance.

mouseUp() methods also receive the coordinates of the point where the mouse was released.
public boolean mouseUp(Event e, int x, int y) {
theList.addItem("mouseUp event at (" + x + "," + y + ")");
return false;
}
mouseDown
The mouseDown() method is called whenever the mouse button is pressed in your applet. In most cases you'll want to wait for a mouseUp before taking any action though.

mouseDown() methods also receive the coordinates of the point where the mouse was released.

public boolean mouseDown(Event e, int x, int y) {
theList.addItem("mouseDown event at (" + x + "," + y + ")");
return false;
}
mouseDrag
mouseDrag() methods occur when a user moves the mouse while holding down the mouse button. mouseDrag() methods receive the coordinates of the point where the mouse is when the event occurs.

public boolean mouseDrag(Event e, int x, int y) {
theList.addItem("mouseDrag event at (" + x + "," + y + ")");
return false;
}
mouseMove
mouseMove methods occur when a user moves the mouse without holding down the mouse button. mouseMove methods receive the coordinates of the point where the mouse is when the event occurs.
public boolean mouseMove(Event e, int x, int y) {
theList.addItem("mouseMove event at (" + x + "," + y + ")");
return false;
}
mouseEnter
Your applet receives a mouseEnter event whenever the cursor enters your applet from somewhere else. You'll also receive the coordinates of the point at which the cursor entered your applet. After this happens its typically followed by a Stream of mouseMoved events as the cursor continues through the applet so it can be hard to see.

public boolean mouseEnter(Event e, int x, int y) {
theList.addItem("mouseEnter event at " + x + "," + y + ")");
return false;
}
mouseExit
Your applet receives a mouseExit event whenever the cursor leaves your applet. You'll also receive the coordinates of the point at which the cursor exited your applet.
public boolean mouseExit(Event e, int x, int y) {
theList.addItem("mouseExit event at (" + x + "," + y + ")");
return false;
}
getFocus
public void getFocus() {
theList.addItem("getFocus event");
}
gotFocus
public void gotFocus() { theList.addItem("gotFocus event"); }
lostFocus
public void lostFocus() {
theList.addItem("lostFocus event");
}
keyDown
A keydown event is generated whenever the user presses a key while your applet is active. An integer keycode is returned indicating which key was pressed. As a general rule you'll want to cast this to a char to get the actual letter.

public boolean keyDown(Event e, int x) {
theList.addItem("The " + (char) x + " key was pressed.");
return false;
}

Here's the revised EventTutor Applet:

Drawing Text
Drawing Graphics: Lines, Circles, Rectangles and Colors
Drawing Rectangles
Next we'll write an applet that fills the screen with lots of randomly sized and positioned rectangles in the style of Piet Mondrian. In the process we'll learn the basics of applet graphics. We're going to take this one step at a time, adding a bit as we go.

In the first applet we'll just draw a rectangle on the screen. We'll get the size of the applet as specified in the HTML file, and then we'll draw a rectangle around the applet to frame it. Here's the code:
//Draw a rectangle

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

public class Mondrian1 extends Applet {

int height, width;

public void init() {
Dimension d = size();
height = d.height;
width = d.width;
repaint();

}

public void paint(Graphics g) {

g.drawRect(0, 0, width, height);
}

}
Compile this applet; move the resulting class file to your classes directory, and create an HTML file that points to it. Set the height of the applet to 300 pixels and the width to 300 pixels as well. Load that file into your browser and what do you see? Probably not what you expected. You should see half a rectangle. What happened to the other half?

This is called a fencepost error. The applet lives in a square 300 pixels tall by 300 pixels wide. However the upper left hand corner of the applet starts at (0, 0), not at (1, 1). This means that the applet includes the points with x and y coordinates between 0 and 299, not between 0 and 300. We drew a rectangle 301 pixels high and 301 pixels wide so the edges were chopped off.

This is fortuitous however. Not only does it allow me the opportunity to digress on fencepost errors (which, although annoying, are far less dangerous in Java than in C since Java does check array boundaries) but it also shows us something else. In Java the coordinate system for an applet begins in the upper left hand corner and increases to the right and down. This is common in computer graphics but is different from the Cartesian coordinate system where the direction of increasing y is generally assumed to be up.

Correcting the fence post error is easy. We just change g.drawRect(0, 0, width, height); to g.drawRect(0, 0, width-1, height-1);
//Draw a rectangle

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

public class Mondrian2 extends Applet {

int height, width;

public void init() {
Dimension d = size();
height = d.height;
width = d.width;
repaint();

}

public void paint(Graphics g) {

g.drawRect(0, 0, width-1, height-1);
}

}
As usual compile this and load it into your browser. If the problem isn't fixed check to make sure that you moved the new class file into the classes directory and that you modified the HTML file to point to Mondrian2.

We've introduced exactly one new statement in all this code, drawRect which is a method in the Graphics class. The line g.drawRect(0, 0, height-1, width-1) instructs the Graphics class g to draw a rectangle beginning at the point (0, 0) and ending at the point (299, 299).

This particular rectangles encompasses the entire applet's visible space. There is nothing to keep us from drawing outside the applet, in fact we did exactly that in our first version where we actually extended the rectangle to (300, 300); but anything we draw there won't be seen by the user.

The drawRect method draws an open rectangle. If we want to draw a filled rectangle we use the fillRect method. Otherwise the syntax is identical. In Mondrian3 we'll draw a filled rectangle in the center of the applet. Here's the code:
//Draw a rectangle

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

public class Mondrian3 extends Applet {

int AppletHeight;
int AppletWidth;
int RectHeight;
int RectWidth;
int RectTop;
int RectLeft;


public void init() {
Dimension d = size();
AppletHeight = d.height;
AppletWidth = d.width;
RectHeight = AppletHeight/3;
RectWidth = AppletWidth/3;
RectTop = (AppletHeight - RectHeight)/2;
RectLeft= (AppletWidth - RectWidth)/2;
repaint();

}

public void paint(Graphics g) {

g.drawRect(0, 0, AppletWidth-1, AppletHeight-1);
g.fillRect(RectLeft, RectTop, RectWidth-1, RectHeight-1);
}

}
This latest example also demonstrates one other thing. Until now you may have thought that we were passing two points to the drawRect and fillRect methods and drawing the rectangle that joins them. This is how rectangles are implemented in QuickDraw on the Mac for example. However if that was the case the preceding rectangle would have been drawn between (100, 100) and (100, 100), a fairly small rectangle. Since that isn't the case our association of the last two variables with width and height must be correct.

The extremely astute reader may object at this point. Until now we've only drawn squares. Although the last two variables passed to drawRect and fillRect must be the height and the width how do we know which is which? The simplest way to tell is to write a test program that draws a non-square rectangle. Let's try that now:
//Draw a rectangle

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

public class Mondrian4 extends Applet {

int RectHeight, RectWidth, RectTop, RectLeft, AppletWidth, AppletHeight;

public void init() {

Dimension d = size();
AppletHeight = d.height;
AppletWidth = d.width;
RectHeight = AppletHeight/3;
RectWidth = (AppletWidth*2)/3;
RectTop = (AppletHeight - RectHeight)/2;
RectLeft= (AppletWidth - RectWidth)/2;

repaint();

}

public void paint(Graphics g) {

g.drawRect(0, 0, AppletWidth-1, AppletHeight-1);
g.fillRect(RectLeft, RectTop, RectWidth-1, RectHeight-1);

}

}
So you see that the third argument is indeed the width and the fourth is the height.

Now that we've learned how to draw rectangles, both filled and unfilled, let's make life a little more exciting by randomly selecting the position and size of the rectangle. To do this we'll need the Math.random() method from java.lang.Math. This method returns a double between 0.0 and 1.0 so we'll need to multiply the result by the applet's height and width to get a reasonably sized rectangle that fits into our applet space. To do this we'll create the following Randomize method:
private int Randomize( int range )
{
double rawResult;
rawResult = Math.random();
return (int) (rawResult * range);

}
This method forces the result of Math.random into an int in the range we require. Pay special attention to the last line. When you see a raw type in parentheses like (int) or (float) it's a cast. Casts change one value type into another. Thus here we're changing a double into an int. The cast rounds as necessary.

Casting in Java is safer than in C or other languages that allow arbitrary casting. Java only lets casts occur when they make sense, such as a cast between a float and an int. However you can't cast between an int and a String for example.
//Draw a rectangle

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

public class Mondrian5 extends Applet {

int RectHeight, RectWidth, RectTop, RectLeft, AppletWidth, AppletHeight;

public void init() {

Dimension d = size();
AppletHeight = d.height;
AppletWidth = d.width;
RectTop = Randomize(AppletHeight);
RectLeft= Randomize(AppletWidth);
RectHeight = Randomize(AppletHeight - RectTop);
RectWidth = Randomize(AppletWidth - RectLeft);

repaint();

}

public void paint(Graphics g) {

g.drawRect(0, 0, AppletWidth-1, AppletHeight-1);
g.fillRect(RectLeft, RectTop, RectWidth-1, RectHeight-1);

}
private int Randomize(int range)
{
double rawResult;

rawResult = Math.random();
return (int) (rawResult * range);

}

}
Occasionally this applet does randomly produce a rectangle that's two small to see so if you don't see anything, reload it. Reload it a few times. Each time you'll see a rectangle of a different size appear in a different place.

Let's make our world a little more colorful. To do this we'll change the rectangle color to red. To do this we'll use a new methods setColor(), part of the Graphics class.
//Draw a colored rectangle

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

public class Mondrian6 extends Applet {

int RectHeight, RectWidth, RectTop, RectLeft, AppletWidth, AppletHeight;

public void init() {

Dimension d = size();
AppletHeight = d.height;
AppletWidth = d.width;
RectTop = Randomize(AppletHeight);
RectLeft= Randomize(AppletWidth);
RectHeight = Randomize(AppletHeight - RectTop);
RectWidth = Randomize(AppletWidth - RectLeft);

repaint();

}

public void paint(Graphics g) {

// g.setBackground(Color.white);
g.setColor(Color.red);
g.drawRect(0, 0, AppletWidth-1, AppletHeight-1);
g.fillRect(RectLeft, RectTop, RectWidth-1, RectHeight-1);

}
private int Randomize(int range)
{
double rawResult;

rawResult = Math.random();
return (int) (rawResult * range);

}

}
The awt predefines a number of colors including:

black
blue
cyan
darkGray
gray
green
lightGray
magenta
orange
pink
red
white
yellow
If these aren't sufficient for your needs, you can define others using the same RGB triple that's used to set background colors on many web pages. You even get to use decimal numbers instead of the hex values you have to use for the bgcolor tag. For example to select a medium gray you'd use Color(127, 127, 127). Pure white would be Color(255, 255, 255). Pure red is (255, 0, 0) and so on.

By using the color constructor we can expand our program to select not only a random rectangle but also a random color for the rectangle. Here's the code:
//Draw a randomly colored rectangle

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

public class Mondrian7 extends Applet {

int RectHeight, RectWidth, RectTop, RectLeft, AppletWidth, AppletHeight;
Color RectColor;

public void init() {

Dimension d = size();
AppletHeight = d.height;
AppletWidth = d.width;
RectTop = Randomize(AppletHeight);
RectLeft= Randomize(AppletWidth);
RectHeight = Randomize(AppletHeight - RectTop);
RectWidth = Randomize(AppletWidth - RectLeft);
RectColor = new Color(Randomize(255),Randomize(255),Randomize(255));

repaint();

}

public void paint(Graphics g) {

// g.setBackground(Color.white);
g.setColor(RectColor);
g.drawRect(0, 0, AppletWidth-1, AppletHeight-1);
g.fillRect(RectLeft, RectTop, RectWidth-1, RectHeight-1);

}
private int Randomize(int range)
{
double rawResult;

rawResult = Math.random();
return (int) (rawResult * range);

}

}
In the next example we're going to draw multiple randomly sized, randomly colored rectangles. Since we want each rectangle to be different we're going to have to move the calculation of the rectangle's shape, position and color into the paint() method. Here's the code:
//Draw many randomly colored rectangles

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

public class Mondrian8 extends Applet {

int RectHeight, RectWidth, RectTop, RectLeft, AppletWidth, AppletHeight;
Color RectColor;
int numberRectangles = 100;
public void init() {

Dimension d = size();
AppletHeight = d.height;
AppletWidth = d.width;

repaint();

}

public void paint(Graphics g) {
g.setColor(Color.black);
g.drawRect(0, 0, AppletWidth-1, AppletHeight-1);
for (int i=0; i <> RectTop = Randomize(AppletHeight);
RectLeft= Randomize(AppletWidth);
RectHeight = Randomize(AppletHeight - RectTop);
RectWidth = Randomize(AppletWidth - RectLeft);
RectColor = new Color(Randomize(255),Randomize(255),Randomize(255));
g.setColor(RectColor);
g.fillRect(RectLeft, RectTop, RectWidth-1, RectHeight-1);
}
}
private int Randomize(int range)
{
double rawResult;

rawResult = Math.random();
return (int) (rawResult * range);

}

}
Finally let's let the HTML specify the number of rectangles to be drawn in one pass. We'll keep the default value as is and only replace it if the HTML includes a Number PARAM.
//Draw many random rectangles

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

public class Mondrian9 extends Applet {

int RectHeight, RectWidth, RectTop, RectLeft, AppletWidth, AppletHeight;
Color RectColor;
int numberRectangles = 100;
public void init() {

Dimension d = size();
AppletHeight = d.height;
AppletWidth = d.width;
String s = getParameter("Number");
if (s != null) {
numberRectangles = Integer.valueOf(s).intValue();
}
repaint();

}

public void paint(Graphics g) {
g.setColor(Color.black);
g.drawRect(0, 0, AppletWidth-1, AppletHeight-1);
for (int i=0; i <> RectTop = Randomize(AppletHeight);
RectLeft= Randomize(AppletWidth);
RectHeight = Randomize(AppletHeight - RectTop);
RectWidth = Randomize(AppletWidth - RectLeft);
RectColor = new Color(Randomize(255),Randomize(255),Randomize(255));
g.setColor(RectColor);
g.fillRect(RectLeft, RectTop, RectWidth-1, RectHeight-1);
}
}
private int Randomize(int range)
{
double rawResult;

rawResult = Math.random();
return (int) (rawResult * range);

}

}
That's all for now, but we'll return to Mondrian at the end of this chapter when we add threading, and show how to draw rectangles continuously.
Exercises
For the artistically inclined: write a version of Mondrian that draws pictures that are more believably in the style of Piet Mondrian. You should probably restrict your color choices and not allow rectangles to overlap.

Keyword : Java, Java Tutorials, Java Tutorial, Tutorial

NEXT -->