Download Text15-IntermediateGFX

Document related concepts
no text concepts found
Transcript
Chapter XV
Intermediate Graphics
Chapter XV Topics
15.1
Introduction
15.2
Using Mouse Events
15.3
Importing Images
15.4
Fixing Image Issues
15.5
New Features with the Deluxe Expo Class
15.6
Multi-Page Output
15.7
Creating a Simple Draw Program
15.8
Creating Clickable Areas in the Applet
15.9
Computer Animation
15.10
The Last Word
Chapter XV
Intermediate Graphics
537
15.1 Introduction
We have finally come to the last chapter. This happens to be my favorite chapter,
and not because it is the “last” one. In this chapter you will learn more advanced
graphics features. These features will not be as advanced as those taught in AP
Computer Science. That is why this chapter is called Intermediate Graphics
while the last chapter in AP Computer Science is called Advanced Graphics.
Aside from being the last chapter, this chapter is special in another way. There
will be no homework exercises for this chapter. There will also be no quizzes and
no test. The information covered in this chapter will not even be part of the Final
Exam. However, there are two major Lab Projects based on the information in
this chapter. At John Paul II High School the first of these two projects counts as
a test grade, and the second counts even more.
While this chapter is divided into different sections like any other chapter, it is
also divided into two distinct halves. The first half of the chapter focuses on the
skills that you will need to complete the first project. The second half of the
chapter focuses on the skills that you will need to complete The Final Project.
15.2 Using Mouse Events
You are about to learn how to use a mouse to interact with graphics displays. In
the spirit of Exposure Java, which means learning repeatedly with small pieces of
new information, you will see many different programs using mouse features. In
many cases one program will be used to address one mouse feature. By the time
that you are finished, you may be surprised that you can do some sophisticated
graphics programming with this information.
Ignore Deprecated API Warning Messages
Java is constantly improving its class and method selection. When newer and
improved classes become available, the older classes are officially labeled
“deprecated” which essentially means they are so "yesterday". When you use a
deprecated class, you get a warning message like the one shown in Figure 15.1.
538
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.1
Please realize that warning messages are not error messages. An error must be
fixed. A warning is just letting you know there may be a better way to do
something. The technique that we will use to achieve mouse interaction is an
older technique. And yes, there is a newer technique which is considered better.
However, the newer and better technique is also more complicated and requires
knowledge of topics taught in AP Computer Science. For this reason, we will use
the older and simpler technique and simply ignore any warning messages about
deprecated classes.
Counting Mouse Clicks
Now let us get the ball rolling with program Java1501.java, in figure 15.2. This
program will count and display the number of times that the mouse is clicked.
Program Java1501.java requires some explanation, because it includes a variety
of new features that will be puzzling at first introduction.
You have already seen the paint method for some time. Applets use the paint
method to display graphics patterns on the monitor. You have also learned that
the paint method is called automatically by the web browser that executes the
bytecode file of an applet. Method paint is not the only method that is called by
the web browser. Method init is executed before paint, if it exists. True to its
name, method init usually performs the job of initializing variables. In program
Java1501.java the init method sets the numClicks integer field to 0.
After method init you see the familiar paint method. Apparently, method paint
is only in charge of displaying a graphics string indicating how many times the
mouse has been clicked.
Chapter XV
Intermediate Graphics
539
Below method paint appears to be another method called mouseDown. There is
no evidence that mouseDown is called anywhere. Is this yet another method that
is called automatically? Well mouseDown is not called like init or paint and it is
not a regular method. It is an event. Events are routines that are not called by
using the identifier of the event, but the events are executed when some special
event occurs. Mouse-type-events occur when the mouse is clicked, released,
moved or dragged. Java has created a special behind-the-scene interface with the
mouse that knows when something new is happening with the mouse.
In the case of Java1501.java something new means that either mouse button is
clicked. It results in calling mouseDown and then mouseDown changes the
numClicks value, as well as calling method repaint. When repaint is called, it
clears the screen and then executes the paint method again. The bottom line is
that every time you click, the number increases.
Figure 15.2
// Java1501.java
// This program counts the number of times a mouse is clicked.
// Both left-clicks and right-clicks are counted.
// using the <mouseDown> event. Ignore the "deprecated API" warning.
import java.applet.Applet;
import java.awt.*;
public class Java1501 extends Applet
{
int numClicks;
public void init()
{
numClicks = 0;
}
public void paint(Graphics g)
{
g.drawString("Mouse is clicked " + numClicks + " times.",20,20);
}
public boolean mouseDown(Event e, int x, int y)
{
numClicks++;
repaint();
return true;
}
}
540
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.2 Continued
Above is the initial output. Below is the output after 7 clicks.
Detecting Mouse Click Coordinates
Each of the programs that follow will demonstrate some new mouse feature. A
brief explanation will detail the actions of the new mouse feature. By now you
should realize that "playing" with the program is the most effective way to learn
new program language concepts. Program Java1502.java, in figure 15.3 shows
that the mouseDown event records the X-coordinate and Y-Coordinate values
when the mouse is clicked in the x and y parameters of the mouseDown event.
Figure 15.3
// Java1502.java
// This program displays the position of the mouse every time it is clicked
// using the <mouseDown> method.
import java.applet.Applet;
import java.awt.*;
Chapter XV
Intermediate Graphics
541
public class Java1502 extends Applet
{
int xCoord, yCoord;
public void paint(Graphics g)
{
g.drawString("Mouse clicked at (" + xCoord + "," + yCoord + ")",20,20);
}
public boolean mouseDown(Event e, int x, int y)
{
xCoord = x;
yCoord = y;
repaint();
return true;
}
}
Figure 15.3 Continued
Determining if the Mouse is In the Applet Window
Program Java1503.java, in figure 15.4 uses both the mouseEnter event and
mouseExit event to determine when the mouse enter or exits the applet window.
Figure 15.4
// Java1503.java
// This program demonstrates how to determine if the mouse is inside or
// outside the Applet window using the <mouseEnter> and <mouseExit> methods.
import java.applet.Applet;
import java.awt.*;
public class Java1503 extends Applet
{
boolean insideApplet;
542
Exposure Java 2012, PreAPCS Edition
05-31-12
public void paint(Graphics g)
{
if (insideApplet)
g.drawString("Mouse is inside applet",20,20);
else
g.drawString("Mouse is outside applet",20,20);
}
public boolean mouseEnter(Event e, int x, int y)
{
insideApplet = true;
repaint();
return true;
}
public boolean mouseExit(Event e, int x, int y)
{
insideApplet = false;
repaint();
return true;
}
}
Figure 15.4 Continued
Checking if the Button is Clicked Once or Twice
The e object in the parameter heading of the mouseDown event has a clickCount
attribute which stores the number of times that a mouse is clicked. Program
Java1504.java, in figure 15.5, demonstrates this concept for single-clicks and
double-clicks. The same technique can also work for triple-clicks, quadrupleclicks, and beyond. Keep in mind that the time delay between first and second
click is based on Windows mouse settings.
Figure 15.5
// Java1504.java
// This program determines if a mouse is clicked once or twice using the
// <clickCount> method. This method works for the left or right button.
Chapter XV
Intermediate Graphics
543
import java.applet.Applet;
import java.awt.*;
public class Java1504 extends Applet
{
boolean singleClick,doubleClick;
public void paint(Graphics g)
{
if (singleClick)
g.drawString("Mouse was clicked once",20,20);
if (doubleClick)
g.drawString("Mouse was clicked twice",20,20);
}
public boolean mouseDown(Event e, int x, int y)
{
switch (e.clickCount)
{
case 1:
singleClick = true;
doubleClick = false;
break;
case 2:
doubleClick = true;
singleClick = false;
}
repaint();
return true;
}
}
Figure 15.5 Continued
Output
after
singleclick:
Output
after
doubleclick:
544
Exposure Java 2012, PreAPCS Edition
05-31-12
Displaying the Mouse Position Continuously
A few programs back the program displayed the mouse position whenever the
mouse was clicked. Program Java1505.java, in figure 15.6, constantly checks
and updates the location of the mouse using the mouseMove event. Any
movement of the mouse triggers the mouseMove event, which stores the latest
coordinate values in the x and y parameters.
Figure 15.6
// Java1505.java
// This program displays the position of the mouse every time it moves
// using the <mouseMove> method.
import java.applet.Applet;
import java.awt.*;
public class Java1505 extends Applet
{
int xCoord, yCoord;
public void paint(Graphics g)
{
g.drawString("Mouse is located at (" + xCoord + "," + yCoord + ")",20,20);
}
public boolean mouseMove(Event e, int x, int y)
{
xCoord = x;
yCoord = y;
repaint();
return true;
}
}
Figure 15.6 Continued
Chapter XV
Intermediate Graphics
545
15.3 Importing Images
Soon you will be working on the first of your two graphics projects. The vast
majority of output in any graphics project is expected to be created by your Java
program with Graphics methods from the Expo class like drawLine,
drawRectangle, and drawCircle. Sometimes it is nice to add a little personal
touch to a project. This is similar to what you observe with the PowerPoint slides
used with Exposure Java. You have probably noticed that the left picture from
figure 15.7 is on the first slide of every PowerPoint presentation. The picture on
the right was created by a former student and will be used in the next program.
Figure 15.7
Pictures like these can be imported into a Java program. Program Java1506.java
in figure 15.8 shows how an image file can be imported and displayed at any
location on the screen.
A new class, Image, enables the importing of pictures. In the init method, the
picture is loaded from external storage then stored in internal memory,
specifically in the Image object picture. The init method does not display the
picture. It links the internal Image object to the external image file. This is
similar what you saw in the last chapter when an internal file object was linked to
an external text file.
In the paint method a new method, drawImage, takes over and displays the
image at a specified coordinate. This coordinate indicates the location of the topleft corner of the image. Note that drawImage is not a method of the Expo class.
It is one of many object methods of the Graphics class. To call this object
method, we must use the graphics object g. You will notice that g is not a
parameter in this method. You may also notice the peculiar last parameter. The
this parameter is required and needs to be used without explanation for now.
546
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.8
// Java1506.java
// This program demonstrates how display to a single graphics image from a .gif file
// at any x,y location on the screen. The same image can be displayed multiple times.
import java.awt.*;
public class Java1506 extends java.applet.Applet
{
Image picture;
public void init()
{
picture = getImage(getDocumentBase(),"LSchram.gif");
}
public void paint(Graphics g)
{
g.drawImage(picture,0,0,this);
g.drawImage(picture,750,200,this);
g.drawImage(picture,350,450,this);
}
}
Chapter XV
Intermediate Graphics
547
Program Java1507.java in figure 15.9 shows that multiple gif files can be
displayed in the same program.
Figure 15.9
// Java1507.java
// This program demonstrates that several different images can be displayed.
import java.awt.*;
public class Java1507 extends java.applet.Applet
{
Image picture1, picture2, picture3, picture4, picture5, picture6;
public void init()
{
picture1 = getImage(getDocumentBase(),"Knight.gif");
picture2 = getImage(getDocumentBase(),"MouseWithCheese.gif");
picture3 = getImage(getDocumentBase(),"smile.gif");
picture4 = getImage(getDocumentBase(),"shark.gif");
picture5 = getImage(getDocumentBase(),"Spider.gif");
picture6 = getImage(getDocumentBase(),"TEDDY.gif");
}
public void paint(Graphics g)
{
g.drawImage(picture1,100,100,this);
g.drawImage(picture2,400,100,this);
g.drawImage(picture3,700,100,this);
g.drawImage(picture4,100,400,this);
g.drawImage(picture5,400,400,this);
g.drawImage(picture6,700,400,this);
}
}
548
Exposure Java 2012, PreAPCS Edition
05-31-12
Program Java1508.java in figure 15.10 shows that importing an animated gif is
no different from importing a normal gif. You will need to execute this program
on a computer to see the actual output. Do not be surprised if your screen seems
to flicker. This is normal with animated gifs.
Figure 15.10
// Java1508.java
// This program demonstrates that animated gifs are inserted in the same way as
// normals gifs. Animated gifs can cause a flickering side-effect on the screen.
import java.awt.*;
public class Java1508 extends java.applet.Applet
{
Image picture1, picture2, picture3, picture4, picture5, picture6;
public void init()
{
picture1 = getImage(getDocumentBase(),"space.gif");
picture2 = getImage(getDocumentBase(),"computer.gif");
picture3 = getImage(getDocumentBase(),"gears.gif");
picture4 = getImage(getDocumentBase(),"butterfly.gif");
picture5 = getImage(getDocumentBase(),"pizza.gif");
picture6 = getImage(getDocumentBase(),"jet.gif");
}
public void paint(Graphics g)
{
g.drawImage(picture1,100,100,this);
g.drawImage(picture2,450,100,this);
g.drawImage(picture3,700,100,this);
g.drawImage(picture4,100,400,this);
g.drawImage(picture5,400,350,this);
g.drawImage(picture6,700,400,this);
}
}
Chapter XV
Intermediate Graphics
549
Gifs are not the only type of image that can be displayed. We can also display
png files. This is demonstrated by program Java1509.java in figure 15.11.
Figure 15.11
// Java1509.java
// This program demonstrates that .png files also work.
import java.awt.*;
public class Java1509 extends java.applet.Applet
{
Image picture1, picture2, picture3, picture4, picture5, picture6;
public void init()
{
picture1 = getImage(getDocumentBase(),"Bunny.png");
picture2 = getImage(getDocumentBase(),"pineapple.png");
picture3 = getImage(getDocumentBase(),"Penguin.png");
picture4 = getImage(getDocumentBase(),"Koala.png");
picture5 = getImage(getDocumentBase(),"house.png");
picture6 = getImage(getDocumentBase(),"bird.png");
}
public void paint(Graphics g)
{
g.drawImage(picture1,100,100,this);
g.drawImage(picture2,400,100,this);
g.drawImage(picture3,700,100,this);
g.drawImage(picture4,100,400,this);
g.drawImage(picture5,400,400,this);
g.drawImage(picture6,700,400,this);
}
}
550
Exposure Java 2012, PreAPCS Edition
05-31-12
Jpg files can also be displayed. This is demonstrated by program Java1510.java
in figure 15.12. Note that jpg files are usually used for photographs.
Figure 15.12
// Java1510.java
// This program demonstrates .jpg files can be used as well.
// .jpg files are typically used for photographs.
import java.awt.*;
public class Java1510 extends java.applet.Applet
{
Image picture1, picture2, picture3, picture4;
public void init()
{
picture1 = getImage(getDocumentBase(),"Paris.jpg");
picture2 = getImage(getDocumentBase(),"LetSleepingDogsLie.jpg");
picture3 = getImage(getDocumentBase(),"AllSmiling.jpg");
picture4 = getImage(getDocumentBase(),"Schrams.jpg");
}
public void paint(Graphics g)
{
g.drawImage(picture1,0,0,this);
g.drawImage(picture2,500,0,this);
g.drawImage(picture3,0,330,this);
g.drawImage(picture4,316,330,this);
}
}
Chapter XV
Intermediate Graphics
551
15.4 Fixing Image Issues
There are a number of things that can prevent an image from being displayed
properly. Maybe the image is not the correct format. Maybe the image is not in
the correct folder. Maybe the image is just too big. Any of these will cause
problems. In this section, we will look at how to fix those problems.
Problem #1 – The Image File has the Wrong Format
Figure 15.13 shows the image that we will attempt to display in the program
Java1511.java, shown in Figure 15.14. The logic of the program seems no
different than the past several programs which also displayed images. There is
one difference however. This image is a bitmap (bmp) file. While Java can
display gif, png, and jpg files, it cannot display bmp files as the output
demonstrates.
Figure 15.13
Figure 15.14
// Java1511.java
// Problem #1 -- The image file has the wrong format.
// This program demonstrates that .bmp files cannot be displayed. Nothing will show up.
// To fix this, load the bitmap file in Paint and resave it as a .gif, .png or .jpg file.
import java.awt.*;
public class Java1511 extends java.applet.Applet
{
Image picture;
552
Exposure Java 2012, PreAPCS Edition
05-31-12
public void init()
{
picture = getImage(getDocumentBase(),"ShortCircuit.bmp");
}
public void paint(Graphics g)
{
g.drawImage(picture,100,100,this);
}
}
Figure 15.14 Continued
There is a solution to this problem. The bitmap file must be converted to a
different format. Keep in mind it is not sufficient to simply rename the file and
give it a different extension. This will simply make the file unusable. You need
to actually convert the file. First you need to load the file in some graphics editor,
like Microsoft Paint. See Figure 15.15. Then you need to choose Save As and
make sure to specify a different file format. See Figure 15.16. Which format
should you choose? Typically photographs are saved as jpg files and simple
drawings are saved as gif files. Sometimes when you try to save a drawing as a
gif you might get a warning stating that “The color quality might be reduced if
you save the picture in this format.” In that case, choose png.
Chapter XV
Intermediate Graphics
553
Figure 15.15
Figure 15.16
554
Exposure Java 2012, PreAPCS Edition
05-31-12
Now, you will have to make a slight change to the program to make things work.
Program Java1511.java is shown again in figure 15.17. Note that the file name
has been altered to reflect the fact that I converted the file to a png file. If you
converted the file to a gif or jpg, you will need to adjust the file name
accordingly. Now when you execute the program, we see the image.
Figure 15.17
// Java1511.java
// Problem #1 -- The image file has the wrong format.
// This program demonstrates that .bmp files cannot be displayed. Nothing will show up.
// To fix this, load the bitmap file in Paint and resave it as a .gif, .png or .jpg file.
import java.awt.*;
public class Java1511 extends java.applet.Applet
{
Image picture;
public void init()
{
picture = getImage(getDocumentBase(),"ShortCircuit. png");
}
public void paint(Graphics g)
{
g.drawImage(picture,100,100,this);
}
}
Chapter XV
Intermediate Graphics
555
Problem #2 – The Image File is Not in the Correct Location
Last chapter we worked with files, and one big deal with a file is that it must be in
the proper folder so it can be found by the program that reads the information
from it. You also have been working with the Expo.java file for a while. What
allows you to use the methods of the Expo class is the fact that Expo.java is
located in the same folder as the program calling its methods. If the file
Expo.java was not in the Programs15 folder, then many of the programs in this
chapter would not even compile.
A similar issue exists with program Java1512.java., shown in Figure 15.18. The
program attempts to display the image file DallasSkyline.png, but nothing shows
up. The file, DallasSkyline.png, does exist, but it is in the wrong folder. Instead
of being with Java1512.java in the Programs15 folder, the file
DallasSkyline.png, is in the Dallas subfolder. It needs to be copied or cut from
the Dallas subfolder, and pasted into the Programs15 folder. Two outputs are
shown. The first shows the blank output when the program cannot find the image
file. The second should the output after the file has been put in the proper folder.
Figure 15.18
// Java1512.java
// Problem #2 -- The image file is not in the correct location.
// This program demonstrates that an image cannot be displayed if it is not in the correct folder.
// When you execute the program, nothing is displayed.
// Move the "DallasSkyline.png" file from the "Dallas" subfolder to the "Programs15" folder
// and execute the program again. After the file is moved, the program should work.
import java.awt.*;
public class Java1512 extends java.applet.Applet
{
Image picture;
public void init()
{
picture = getImage(getDocumentBase(),"DallasSkyline.png");
}
public void paint(Graphics g)
{
g.drawImage(picture,0,100,this);
}
}
556
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.18 Continued
Java1512.java Output – Before the file is moved
Java1512.java Output – After the file is moved
Chapter XV
Intermediate Graphics
557
Problem #3 – The Image File is Too Big
In the Programs15 folder is a file called Castillo.JPG. If you were to doubleclick this file, you would see image displayed in some sort of Picture Viewer or
Photo Viewer like what is shown in Figure 15.19. This is a picture of El Castillo
de San Felipe del Morro in San Juan, Puerto Rico. I am showing you this picture
not to give you a geography lesson, but to make a point. This looks like a normal
size picture that should have no problem being displayed in a Java program. In
reality, the picture is huge! Its dimensions are 3008 by 2000 pixels. Program
Java1513.java in Figure 15.20 will try to demonstrate just how huge.
Figure 15.19
Figure 15.20
// Java1513.java
// Problem #3 -- The image file is too big.
// This program will be used to demonstrate what to do when a picture is too big.
import java.awt.*;
558
Exposure Java 2012, PreAPCS Edition
05-31-12
public class Java1513 extends java.applet.Applet
{
Image picture;
public void init()
{
picture = getImage(getDocumentBase(),"castillo.jpg");
}
public void paint(Graphics g)
{
Expo.setFont(g,"Snap ITC",Font.PLAIN,48);
Expo.drawString(g,"El Castillo de San Felipe del Morro",15,60);
g.drawImage(picture,0,100,this);
}
}
Figure 15.20 Continued
The picture is so big, that on a normal display of 1000 by 650, we are only about
to see a little bit of the sky from the top-left corner. I also tried to execute the
program on a 48 inch plasma screen. This did let me see more of the picture, but
it was only about ¼ of the entire picture. When a photograph is taken with a
digital camera, it creates a huge jpg file. This allows pictures to be blown up to
poster size. In our case, we want to go the other direction and make the picture fit
on our normal sized screen. This can be done in a variety of ways.
Chapter XV
Intermediate Graphics
559
Problem #3 – Solution #1 – Resize the Image
As before, this solution involves loading the picture in a Graphics Editor.
Microsoft Paint will be used again in this example. Any decent graphics editor
should have the ability to resize the image. See Figure 15.21.
Figure 15.21
When resizing, you either resize with Percentages or Pixels. If you select
Percentage and enter 50 for both dimensions, you will make the picture ½ as tall
and ½ as wide – which means it now is ¼ the area. In our case, I know the exact
size I want the picture to be, so I selected Pixels. This is shown in Figure 15.22.
Note that it shows the current dimensions of the picture are 3008 by 2000.
I then changed the Vertical value from 2000 to 550. Look at Figure 15.23. Note
that the Horizontal value also changed. This is because Maintain Aspect Ratio is
checked. As long as this is checked, whenever you change one dimension, the
other dimension will automatically change in such a way that the proportions of
the picture remain the same.
Now look at Figure 15.24. This shows the picture after it is resized. Save the
picture and execute the program again. You will not need to make any changes to
the program. Figure 15.25 shows the output of the resized image.
560
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.22
Figure 15.23
Figure 15.24
Chapter XV
Intermediate Graphics
561
Figure 15.25
Problem #3 – Solution #2 – Specify Image Dimensions
Resizing does have the benefit that the picture will use less memory, but memory
is becoming less and less of an issue. You also may not want to alter the existing
image. In this case, we will leave the actual image alone. We will not resize it at
all. Instead, we will add a couple parameters to the drawImage command to
specify the dimensions as shown in figure 15.26. You may wonder why I picked
the numbers 752 and 500. Well, the actual dimensions of the image are 3008 by
2000. I simply divided both numbers by 4. The result is the displayed image will
be ¼ the width and ¼ the height (or 1/16 the total area) of the actual image.
Figure 15.26
// Java1513.java
// Problem #3 -- The image file is too big.
// This program will be used to demonstrate what to do when a picture is too big.
import java.awt.*;
public class Java1513 extends java.applet.Applet
{
Image picture;
562
Exposure Java 2012, PreAPCS Edition
05-31-12
public void init()
{
picture = getImage(getDocumentBase(),"castillo.jpg");
}
public void paint(Graphics g)
{
Expo.setFont(g,"Snap ITC",Font.PLAIN,48);
Expo.drawString(g,"El Castillo de San Felipe del Morro",15,60);
g.drawImage(picture,0,100,752,500,this);
}
}
Figure 15.26 Continued
Figure 15.27 shows the output of the program if the dimension parameters were
changed to 376 and 250. Now the image will be ⅛ the width and ⅛ the height
(or 1/64 the total area) of the actual image.
Chapter XV
Intermediate Graphics
563
Figure 15.27
Figure 15.28 shows what happens if you do not alter the dimensions
proportionally. In this output the horizontal dimension was changed to 1000, but
the vertical dimension was left at 250. So we did not maintain aspect ratio and
therefore, the picture is warped.
Figure 15.28
564
Exposure Java 2012, PreAPCS Edition
05-31-12
Problem #3 – Solution #3 – Crop the Image
When you have the problem of a really huge picture, the solution is not always
related to the size of the actual image or the displayed image. What if you only
need to display a small piece of the picture? In this case cropping works out
better than resizing. Any decent graphics editor should also give you the ability
to crop your picture.
Microsoft Paint allows cropping in a round-about sense. There are cropping
handles available, but they are only on the right side and bottom of the image. If
you want to crop the top or the left side, you need to flip the picture and then flip
it back. There is another way to crop in Microsoft Paint that does not require
flipping the image.
Look at Figure 15.29. Here the picture is really big again, but I scrolled to the
middle of the picture and then used Select tool to outline a rectangular region of
what I actually want to keep. In this case, it is the tower. I then copied the
highlighted region and pasted it in a new file. See Figure 15.30. After saving this
file under the name castillo.JPG I can execute the program again. See Figure
15.31.
Note: Make sure to remove the extra 2 parameters from the drawImage
command so we will see the actual size of the cropped image.
Figure 15.29
Chapter XV
Intermediate Graphics
565
Figure 15.30
Figure 15.31
566
Exposure Java 2012, PreAPCS Edition
05-31-12
15.5 New Features with the Deluxe Expo Class
Ever since Chapter 4, you have been using the Expo class. The primary purpose
for this class was to simplify the process of working with graphics. It also
simplifies the processes of generating random numbers and keyboard input.
While the Expo class that you have been using has a lot of methods, it is actually
the slimmed down version of the Expo class. There actually are many more
methods, and colors available. For this final chapter, you will be using the Deluxe
Expo class. All of the methods and colors that you already know still work. The
Deluxe Expo class just gives you more. For example, program Java1514.java, in
Figure 15.32 shows that the Deluxe Expo class has 85 colors. You may
remember that the Slimmed Down Expo class has 36.
Figure 15.32
// Java1514.java
// This program demonstrates 84 of the 85 colors of the Deluxe Expo class
// There is no white circle drawn since white is the background color.
// NOTE: The 10 primary colors in the Deluxe Expo class are
//
red, green, blue, orange, cyan, magenta, yellow, gray, pink and tan.
//
Each of these colors actually has 5 shades.
//
Example: The 5 shades of red are red, darkRed, lightRed, darkerRed and lighterRed.
//
There are also 35 special colors like lime, teal, navy and chartreuse to name a few.
import java.awt.*;
import java.applet.*;
public class Java1514 extends Applet
{
public void paint(Graphics g)
{
int radius = 60;
Expo.setColor(g,Expo.darkerRed);
Expo.setColor(g,Expo.darkRed);
Expo.setColor(g,Expo.red);
Expo.setColor(g,Expo.lightRed);
Expo.setColor(g,Expo.lighterRed);
Expo.setColor(g,Expo.brown);
Expo.setColor(g,Expo.violet);
Expo.setColor(g,Expo.darkerGreen);
Expo.setColor(g,Expo.darkGreen);
Expo.setColor(g,Expo.green);
Expo.setColor(g,Expo.lightGreen);
Expo.setColor(g,Expo.lighterGreen);
Expo.setColor(g,Expo.darkerBlue);
Expo.setColor(g,Expo.darkBlue);
Expo.setColor(g,Expo.blue);
Expo.setColor(g,Expo.lightBlue);
Expo.setColor(g,Expo.lighterBlue);
Expo.setColor(g,Expo.purple);
Expo.setColor(g,Expo.turquoise);
Expo.setColor(g,Expo.darkerOrange);
Expo.setColor(g,Expo.darkOrange);
Expo.setColor(g,Expo.orange);
Expo.setColor(g,Expo.lightOrange);
Expo.setColor(g,Expo.lighterOrange);
Expo.fillCircle(g, 60, 60,radius);
Expo.fillCircle(g,140, 60,radius);
Expo.fillCircle(g,220, 60,radius);
Expo.fillCircle(g,300, 60,radius);
Expo.fillCircle(g,380, 60,radius);
Expo.fillCircle(g,460, 60,radius);
Expo.fillCircle(g,540, 60,radius);
Expo.fillCircle(g,620, 60,radius);
Expo.fillCircle(g,700, 60,radius);
Expo.fillCircle(g,780, 60,radius);
Expo.fillCircle(g,860, 60,radius);
Expo.fillCircle(g,940, 60,radius);
Expo.fillCircle(g, 60,140,radius);
Expo.fillCircle(g,140,140,radius);
Expo.fillCircle(g,220,140,radius);
Expo.fillCircle(g,300,140,radius);
Expo.fillCircle(g,380,140,radius);
Expo.fillCircle(g,460,140,radius);
Expo.fillCircle(g,540,140,radius);
Expo.fillCircle(g,620,140,radius);
Expo.fillCircle(g,700,140,radius);
Expo.fillCircle(g,780,140,radius);
Expo.fillCircle(g,860,140,radius);
Expo.fillCircle(g,940,140,radius);
Chapter XV
Intermediate Graphics
567
Expo.setColor(g,Expo.darkerCyan);
Expo.setColor(g,Expo.darkCyan);
Expo.setColor(g,Expo.cyan);
Expo.setColor(g,Expo.lightCyan);
Expo.setColor(g,Expo.lighterCyan);
Expo.setColor(g,Expo.plum);
Expo.setColor(g,Expo.indigo);
Expo.setColor(g,Expo.darkerMagenta);
Expo.setColor(g,Expo.darkMagenta);
Expo.setColor(g,Expo.magenta);
Expo.setColor(g,Expo.lightMagenta);
Expo.setColor(g,Expo.lighterMagenta);
Expo.fillCircle(g, 60,220,radius);
Expo.fillCircle(g,140,220,radius);
Expo.fillCircle(g,220,220,radius);
Expo.fillCircle(g,300,220,radius);
Expo.fillCircle(g,380,220,radius);
Expo.fillCircle(g,460,220,radius);
Expo.fillCircle(g,540,220,radius);
Expo.fillCircle(g,620,220,radius);
Expo.fillCircle(g,700,220,radius);
Expo.fillCircle(g,780,220,radius);
Expo.fillCircle(g,860,220,radius);
Expo.fillCircle(g,940,220,radius);
Expo.setColor(g,Expo.darkerYellow);
Expo.setColor(g,Expo.darkYellow);
Expo.setColor(g,Expo.yellow);
Expo.setColor(g,Expo.lightYellow);
Expo.setColor(g,Expo.lighterYellow);
Expo.setColor(g,Expo.aqua);
Expo.setColor(g,Expo.aquaMarine);
Expo.setColor(g,Expo.darkerPink);
Expo.setColor(g,Expo.darkPink);
Expo.setColor(g,Expo.pink);
Expo.setColor(g,Expo.lightPink);
Expo.setColor(g,Expo.lighterPink);
Expo.fillCircle(g, 60,300,radius);
Expo.fillCircle(g,140,300,radius);
Expo.fillCircle(g,220,300,radius);
Expo.fillCircle(g,300,300,radius);
Expo.fillCircle(g,380,300,radius);
Expo.fillCircle(g,460,300,radius);
Expo.fillCircle(g,540,300,radius);
Expo.fillCircle(g,620,300,radius);
Expo.fillCircle(g,700,300,radius);
Expo.fillCircle(g,780,300,radius);
Expo.fillCircle(g,860,300,radius);
Expo.fillCircle(g,940,300,radius);
Expo.setColor(g,Expo.goldenRod);
Expo.setColor(g,Expo.gold);
Expo.setColor(g,Expo.silver);
Expo.setColor(g,Expo.bronze);
Expo.setColor(g,Expo.teal);
Expo.setColor(g,Expo.maroon);
Expo.setColor(g,Expo.fuschia);
Expo.setColor(g,Expo.lavender);
Expo.setColor(g,Expo.lime);
Expo.setColor(g,Expo.navy);
Expo.setColor(g,Expo.chartreuse);
Expo.setColor(g,Expo.fireBrick);
Expo.fillCircle(g, 60,380,radius);
Expo.fillCircle(g,140,380,radius);
Expo.fillCircle(g,220,380,radius);
Expo.fillCircle(g,300,380,radius);
Expo.fillCircle(g,380,380,radius);
Expo.fillCircle(g,460,380,radius);
Expo.fillCircle(g,540,380,radius);
Expo.fillCircle(g,620,380,radius);
Expo.fillCircle(g,700,380,radius);
Expo.fillCircle(g,780,380,radius);
Expo.fillCircle(g,860,380,radius);
Expo.fillCircle(g,940,380,radius);
Expo.setColor(g,Expo.moccasin);
Expo.setColor(g,Expo.salmon);
Expo.setColor(g,Expo.olive);
Expo.setColor(g,Expo.khaki);
Expo.setColor(g,Expo.crimson);
Expo.setColor(g,Expo.orchid);
Expo.setColor(g,Expo.sienna);
Expo.setColor(g,Expo.melon);
Expo.setColor(g,Expo.tangerine);
Expo.setColor(g,Expo.terraCotta);
Expo.setColor(g,Expo.pumpkin);
Expo.setColor(g,Expo.mahogany);
Expo.fillCircle(g, 60,460,radius);
Expo.fillCircle(g,140,460,radius);
Expo.fillCircle(g,220,460,radius);
Expo.fillCircle(g,300,460,radius);
Expo.fillCircle(g,380,460,radius);
Expo.fillCircle(g,460,460,radius);
Expo.fillCircle(g,540,460,radius);
Expo.fillCircle(g,620,460,radius);
Expo.fillCircle(g,700,460,radius);
Expo.fillCircle(g,780,460,radius);
Expo.fillCircle(g,860,460,radius);
Expo.fillCircle(g,940,460,radius);
Expo.setColor(g,Expo.darkerTan);
Expo.setColor(g,Expo.darkTan);
Expo.setColor(g,Expo.tan);
Expo.setColor(g,Expo.lightTan);
Expo.setColor(g,Expo.lighterTan);
Expo.setColor(g,Expo.amber);
Expo.setColor(g,Expo.black);
Expo.setColor(g,Expo.darkerGray);
Expo.setColor(g,Expo.darkGray);
Expo.setColor(g,Expo.gray);
Expo.setColor(g,Expo.lightGray);
Expo.setColor(g,Expo.lighterGray);
Expo.fillCircle(g, 60,540,radius);
Expo.fillCircle(g,140,540,radius);
Expo.fillCircle(g,220,540,radius);
Expo.fillCircle(g,300,540,radius);
Expo.fillCircle(g,380,540,radius);
Expo.fillCircle(g,460,540,radius);
Expo.fillCircle(g,540,540,radius);
Expo.fillCircle(g,620,540,radius);
Expo.fillCircle(g,700,540,radius);
Expo.fillCircle(g,780,540,radius);
Expo.fillCircle(g,860,540,radius);
Expo.fillCircle(g,940,540,radius);
}
}
568
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.32 Continued
Drawing Rounded Rectangles
Drawing rectangles is nothing new, but what about drawing rectangles with
rounded corners? There are many new methods with the Deluxe Expo class and
drawRoundedRectangle is one of them. This new method has the same
parameters as drawRectangle with one exception, there is an extra parameter
which determine how round the corners will be.
Drawing Spirals, Bursts and Random Bursts
These three methods: drawSpiral, drawBurst and drawRandomBurst are
grouped together because they all use the same parameters as drawCircle. The
two burst methods have one addition parameter which determines the number of
lines which burst forth from the center. Exactly what these methods do can be
best understood by looking the program Java1515.java, in Figure 15.33, and its
output. The drawRoundedRectangle method is also demonstrated in this
program.
Chapter XV
Intermediate Graphics
569
Figure 15.33
// Java1515.java
// This program demonstrates the drawSpiral, drawBurst and drawRandomBurst
// methods of the Deluxe Expo class.
// All three of these methods share the same parameters as drawCircle.
// The two "Burst" methods have an additional parameter for the number of lines.
// It also demonstrates the drawRoundedRectangle method of the Deluxe Expo class.
// It shares the same parameters as drawRectangle, except there is an extra parameter
// to control how "rounded" the corners will be.
import java.awt.*;
import java.applet.*;
public class Java1515 extends Applet
{
public void paint(Graphics g)
{
Expo.drawRoundedRectangle(g,10,20,990,300,25);
Expo.drawSpiral(g,180,160,100);
Expo.drawBurst(g,500,160,100,8);
Expo.drawRandomBurst(g,820,160,100,300);
Expo.drawRoundedRectangle(g,10,320,990,640,100);
Expo.drawSpiral(g,180,480,150);
Expo.drawBurst(g,500,480,150,40);
Expo.drawRandomBurst(g,820,480,150,5000);
}
}
570
Exposure Java 2012, PreAPCS Edition
05-31-12
drawThick Methods
When you first learned about graphics, you learned about various draw methods
like drawRectangle, drawCircle, drawOval, drawPolygon, etc.
You also
learned that most draw methods have a corresponding fill method like
fillRectangle, fillCircle, fillOval, fillPolygon, etc. The fill methods have the
same parameters as their corresponding draw methods. With the Deluxe Expo
class, we now also have drawThick methods. If a draw method is like drawing
with a pencil, a drawThick method is like drawing with a paint brush. The
parameters for drawThick methods are also the same as their corresponding draw
method with one exception. There is one extra parameter to determine the
thickness. Program Java1516.java, in Figure 15.34, demonstrates several of
these drawThick methods.
Figure 15.34
// Java1516.java
// This program demonstrates the "drawThick" methods of the Deluxe Expo class.
// All "draw" methods in the Deluxe Expo class have a corresponding "drawThick"
// method with the same parameters, except that the "drawThick" methods have
// an extra parameter to control the "thickness".
import java.awt.*;
import java.applet.*;
public class Java1516 extends Applet
{
public void paint(Graphics g)
{
int t = 12; // thickness
Expo.setColor(g,Expo.blue);
Expo.drawThickLine(g,100,80,900,80,t);
Expo.drawThickRectangle(g,50,30,950,620,t);
Expo.drawThickCircle(g,500,310,200,t);
Expo.drawThickOval(g,400,300,30,40,t);
Expo.drawThickStar(g,400,300,100,10,t);
Expo.drawThickOval(g,600,300,30,40,t);
Expo.drawThickStar(g,600,300,90,6,t);
Expo.drawThickArc(g,500,415,105,65,90,270,t);
Expo.drawThickRoundedRectangle(g,100,100,200,600,25,t);
Expo.drawThickRoundedRectangle(g,800,100,900,500,50,t);
Expo.drawThickSpiral(g,280,115,100,t);
Expo.drawThickSpiral(g,700,115,100,t);
Expo.setColor(g,Expo.red);
Expo.drawThickBurst(g,150,350,150,20,t);
Expo.drawThickRandomBurst(g,850,350,150,300,t);
Expo.setColor(g,Expo.darkGreen);
Expo.drawThickRegularPolygon(g,150,555,40,3,t);
Expo.drawThickRegularPolygon(g,250,555,40,4,t);
Expo.drawThickRegularPolygon(g,350,555,40,5,t);
Expo.drawThickRegularPolygon(g,450,555,40,6,t);
Expo.drawThickRegularPolygon(g,550,555,40,7,t);
Expo.drawThickRegularPolygon(g,650,555,40,8,t);
Expo.drawThickRegularPolygon(g,750,555,40,9,t);
Expo.drawThickRegularPolygon(g,850,555,40,10,t);
}
}
Chapter XV
Intermediate Graphics
571
Figure 15.34 Continued
Keyboard Input from a GUI Window
You have used methods like enterInt to enter information from the keyboard in a
text program. Methods like this will not work in a graphics program. You may
remember that System.out.println also does not work on a graphics screen. We
need to use the drawstring method instead. For keyboard input from a GUI
window, the Deluxe Expo class provides enterIntGUI, enterDoubleGUI,
enterCharGUI, and enterStringGUI. Two of these methods, enterIntGUI and
enterStringGUI are demonstrated in program Java1517.java, shown in Figure
15.35. enterStringGUI is used to enter the file name of an image. enterIntGUI
is used to enter how many times you wish the image displayed randomly on the
screen. Two important details must be noted here. First, the enter methods are
called from the init method. If you tried to call them from the paint method they
would keep popping up on the screen every time the screen refreshes. Second, the
prompt for each input is now a String parameter for each enter method.
Figure 15.35
// Java1517.java
// This program shows how to have user input in a graphics program with the
// enterIntGUI and enterStringGUI methods of the Deluxe Expo class.
// Methods enterDoubleGUI and enterCharGUI are also available.
572
Exposure Java 2012, PreAPCS Edition
05-31-12
import java.awt.*;
public class Java1517 extends java.applet.Applet
{
int amount;
String imageFile;
Image picture;
public void init()
{
String imageFile = Expo.enterStringGUI("What image do you wish to display?");
picture = getImage(getDocumentBase(), imageFile);
amount = Expo.enterIntGUI("How many times do you wish to display this image?");
}
public void paint(Graphics g)
{
for (int j = 1; j <=amount; j++)
{
int x = Expo.random(0,900);
int y = Expo.random(0,550);
g.drawImage(picture,x,y,this);
}
}
}
Figure 15.35 Continued
Chapter XV
Intermediate Graphics
573
Figure 15.35 Continued
Deluxe Version of Expo.html
As before, you are provided with the file Expo.html which documents all of the
methods in the Deluxe Expo class (both old and new). See Figure 15.36.
Figure 15.36
574
Exposure Java 2012, PreAPCS Edition
05-31-12
15.6 Multi-Page Output
This is the last section that is part of “PART-1”. In this section we will look at a
program which generates multiple pages of output, similar to a Slide Show or a
PowerPoint presentation. This is made possible by using the mouseDown event
that was introduced at the beginning of the chapter.
Program Java1518.java, in figure 15.37, demonstrates a short three-page Slide
Show. All of the programming features used in this program have been explained
earlier. You may not have realized that they could be used for this purpose. This
program is going to lead right into the first of the two big graphics projects.
Figure 15.37
// Java1518.java
// This program shows how to display multiple pages of graphics output.
import java.awt.*;
public class Java1518 extends java.applet.Applet
{
int numClicks;
Image picture1, picture2, picture3, picture4, picture5;
public void init()
{
numClicks = 0;
picture1 = getImage(getDocumentBase(),"LSchram.gif");
picture2 = getImage(getDocumentBase(),"JSchram.jpg");
picture3 = getImage(getDocumentBase(),"nederlands.gif");
picture4 = getImage(getDocumentBase(),"leon&isolde.jpg");
picture5 = getImage(getDocumentBase(),"JPIILogo.jpg");
// The following MediaTracker/try/catch code ensures that
// all images are loaded before the program continues.
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(picture1,1);
tracker.addImage(picture2,1);
tracker.addImage(picture3,1);
tracker.addImage(picture4,1);
tracker.addImage(picture5,1);
try
{
tracker.waitForAll();
}
catch(InterruptedException e)
{
System.out.println(e);
}
}
public void paint(Graphics g)
{
switch (numClicks)
{
case 0 : page1(g); break;
case 1 : page2(g); break;
case 2 : page3(g); break;
}
}
Chapter XV
Intermediate Graphics
575
public boolean mouseDown(Event e, int x, int y)
{
numClicks++;
repaint();
return true;
}
public void page1(Graphics g)
{
Expo.setFont(g,"Arial",Font.BOLD,100);
Expo.drawString(g,"TITLE PAGE",218,100);
Expo.setColor(g,Expo.yellow);
Expo.drawThickPreciseSpiral(g,510,370,275,50,15);
Expo.setColor(g,Expo.red);
Expo.fillStar(g,510,370,175,8);
Expo.setColor(g,Expo.green);
Expo.drawThickStar(g,510,370,225,8,25);
Expo.setColor(g,Expo.blue);
Expo.drawThickStar(g,510,370,275,8,25);
g.drawImage(picture1,425,285,this);
Expo.setFont(g,"Times Roman",Font.PLAIN,20);
Expo.drawString(g,"My name is Leon Schram.",30,300);
Expo.drawString(g,"Click once to continue.",760,550);
}
public void page2(Graphics g)
{
Expo.setFont(g,"Algerian",Font.BOLD,100);
Expo.drawString(g,"PAGE 2",200,100);
Expo.setColor(g,Expo.blue);
Expo.fillRectangle(g,100,250,900,500);
Expo.setColor(g,Expo.chartreuse);
g.drawImage(picture3,200,300,this);
g.drawImage(picture4,500,280,this);
Expo.setColor(g,Expo.blue);
Expo.setFont(g,"Times Roman",Font.PLAIN,20);
Expo.drawString(g,"I was born in the Netherlands in 1945 and married my sweet wife Isolde in
1967.",100,200);
Expo.drawString(g,"Click once to continue.",750,550);
}
public void page3(Graphics g)
{
Expo.setFont(g,"Impact",Font.BOLD,100);
Expo.drawString(g,"PAGE 3",200,100);
Expo.setColor(g,Expo.darkGreen);
Expo.fillRoundedRectangle(g,460,170,960,515,50);
g.drawImage(picture5,150,225,this);
g.drawImage(picture2,500,193,this);
Expo.setFont(g,"Times Roman",Font.PLAIN,20);
Expo.drawString(g,"I teach Computer Science at John Paul II High School with my son
John.",100,150);
Expo.drawString(g,"Click once to continue.",750,550);
}
}
576
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.37 Continued
Chapter XV
Intermediate Graphics
577
Figure 15.34 Continued
15.7 Creating a Simple Draw Program
“PART-2” of this chapter begins here. We are now working on the Final
Graphics Project which will be the biggest assignment of the year. Several
different things will be shown to you. It will be up to you to decide what features
to incorporate into your Final Graphics Project, and how.
The Start of a Simple Draw Program
Creating a Draw Program will require the use of several Mouse Events. The
simplest draw program would simply give you the ability to draw dots on the
screen. That will be our starting point. Program Java1519.java, in figure 15.38,
578
Exposure Java 2012, PreAPCS Edition
05-31-12
uses the mouseDown event to store the coordinate where someone has just
clicked the mouse. That coordinate is then used to draw a small, red square.
This program example and many other mouse routine programs cannot be fully
comprehended by reading the text alone. You must execute the program
examples to understand the actual actions of the mouse routines.
Figure 15.38
// Java1519.java
// This program draws a small square at every mouse click position.
// There are 2 problems with the program:
// First, it draws a square in the upper left hand corner automatically before we have a chance to do anything.
// Second, it will only draws one square at a time.
import java.applet.Applet;
import java.awt.*;
public class Java1519 extends Applet
{
int xCoord;
int yCoord;
public void paint(Graphics g)
{
Expo.setColor(g,Expo.red);
Expo.fillRectangle(g,xCoord,yCoord,xCoord+15,yCoord+15);
}
public boolean mouseDown(Event e, int x, int y)
{
xCoord = x;
yCoord = y;
repaint();
return true;
}
}
Java1519.java – Initial Output
Chapter XV
Intermediate Graphics
579
Figure 15.38 Continued
Java1519.java – Output after clicking somewhere else on the screen
There are two issues with this program. First, there is a red square already on the
screen even before you have had a chance to click anywhere. This is because the
default values for xCoord and yCoord are both 0. The result it a dot is draw in
the top-left corner (coordinate 0,0) at the very beginning of the program. The
second problem is that you are only able to draw one dot at a time. Every time
you click to draw a new dot, the old dot is erased. This is caused by repaint.
Remember that when repaint is called it first clears the screen and then calls the
paint again.
Program Java1520.java in figure 15.39 addresses one of the issues from the
previous program. Specifically, the issue of the red square that shows up in the
upper-left-hand corner before you have clicked on anything. This happens
because method paint is called before the mouse is ever touched. This causes one
initial square to be drawn in the applet. This problem is solved with the use of a
boolean variable firstPaint. Variable firstPaint is initialized to true in the init
method and prevents drawing a rectangle until the second time that method paint
is visited.
Figure 15.39
// Java1520.java
// This program cures the problem of the initial red square by adding a "firstPaint" boolean variable.
import java.applet.Applet;
import java.awt.*;
public class Java1520 extends Applet
{
int xCoord;
int yCoord;
boolean firstPaint;
580
Exposure Java 2012, PreAPCS Edition
05-31-12
public void init()
{
firstPaint = true;
}
public void paint(Graphics g)
{
if (firstPaint)
firstPaint = false;
else
{
Expo.setColor(g,Expo.red);
Expo.fillRectangle(g,xCoord,yCoord,xCoord+15,yCoord+15);
}
}
public boolean mouseDown(Event e, int x, int y)
{
xCoord = x;
yCoord = y;
repaint();
return true;
}
}
Figure 15.39 Continued
Java1520.java – Initial Output
Java1520.java – Output after clicking somewhere else on the screen
Chapter XV
Intermediate Graphics
581
OK, we have fixed the first problem. When the program starts, the screen is clear
and there is no initial square. We still have the problem of only being able to see
one square at a time. If we are trying to create a paint program, a single square
simply will not do. So how do you draw anything and keep the drawing on the
screen? The previous program drew many fat pixels, but each time that paint is
called, it clears the screen and only displays the newest pixel.
The Magic of Method update
Program Java1521.java, in figure 15.40, shows the solution. There is a special
method called update. You will notice that this method is not called explicitly
anywhere in the program; however, simply by having it present in the program it
changes what happens when repaint is called. Usually repaint does 2 things.
First it clears the applet window, and second it calls the paint method. When the
update method is present, the repaint method does not clear the applet window at
all. It simply calls the paint method.
Figure 15.40
// Java1521.java
// This program adds the clever "update" method which prevents the
// computer from clearing the paint window every time it is refreshed.
// This allows you to draw more than one square at a time.
import java.applet.Applet;
import java.awt.*;
public class Java1521 extends Applet
{
int xCoord;
int yCoord;
boolean firstPaint;
public void init()
{
firstPaint = true;
}
public void paint(Graphics g)
{
if (firstPaint)
firstPaint = false;
else
{
Expo.setColor(g,Expo.red);
Expo.fillRectangle(g,xCoord,yCoord,xCoord+15,yCoord+15);
}
}
582
Exposure Java 2012, PreAPCS Edition
05-31-12
public boolean mouseDown(Event e, int x, int y)
{
xCoord = x;
yCoord = y;
repaint();
return true;
}
public void update(Graphics g)
{
paint(g);
}
}
Figure 15.40 Continued
Creating a Freehand Pencil Tool
OK, we can draw multiple dots on the screen. A paint program requires more
than just dots. How about the ability to draw freehand? A pencil tool would be
useful. We only need to make a couple small changes to program Java1521.java,
to make this work. The first change is simply to make the square smaller. We
want a pencil took, not a thick marker (at least not at this time). The
fillRectangle command has been replaced with drawPoint. The second change
involved a new mouse event. We will change mouseDown to mouseDrag. You
have seen mouseDown and you have seen mouseMove. mouseDrag is
Chapter XV
Intermediate Graphics
583
essentially a combination of the 2 because to drag the mouse means to move it
while the button is down. When you execute program Java1522.java in figure
15.41, you should see that it behaves very much like a pencil tool in a typical
paint program.
Figure 15.41
// Java1522.java
// This program changes "mouseDown" to "mouseDrag" and makes the square smaller.
// This should create the effect of having a freehand pencil.
import java.applet.Applet;
import java.awt.*;
public class Java1522 extends Applet
{
int xCoord,yCoord;
public void init()
{
xCoord = 0;
yCoord = 0;
}
public void paint(Graphics g)
{
Expo.setColor(g,Expo.red);
Expo.drawPoint(g,xCoord,yCoord);
}
public boolean mouseDrag(Event e, int x, int y)
{
xCoord = x;
yCoord = y;
repaint();
return true;
}
public void update(Graphics g)
{
paint(g);
}
}
584
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.41 Continued
Drawing Lines
Another feature that paint programs typically have is the ability to draw straight
lines. Program Java1523.java in figure 15.42, is the first of 3 programs that will
demonstrate drawing lines. To draw a line you need to consider what a line
actually is. By definition a line is the connection of 2 points. When we want to
draw a single point, we simply used mouseDown because all we needed was one
point and where we clicked the mouse is where the pixel was drawn. Now we
want a line. Think of what you do in a normal paint program. You move your
cursor to the beginning of the line and press down the move button, then you draw
and release at the end of the line. This means we need to store 2 points to
successfully draw a line. Where you press down the mouse is the beginning of
the line. Where you release the mouse is the end of the line. When you execute
program Java1523.java do not be surprised if at first it looks like nothing is
happening. This is because the line will not show up until you release the mouse.
Chapter XV
Intermediate Graphics
585
Figure 15.42
// Java1523.java
// This program draws a straight line from the point where the mouse is clicked
// to the point where the mouse is released.
import java.applet.Applet;
import java.awt.*;
public class Java1523 extends Applet
{
int startX,startY,endX,endY;
public void paint(Graphics g)
{
Expo.drawLine(g,startX,startY,endX,endY);
}
public boolean mouseDown(Event e, int x, int y)
{
startX = x;
startY = y;
return true;
}
public boolean mouseUp(Event e, int x, int y)
{
endX = x;
endY = y;
repaint();
return true;
}
}
586
Exposure Java 2012, PreAPCS Edition
05-31-12
One thing you probably noticed from program Java1523.java is that the drawing
of the line was a little awkward. You could not see the line as you drew it. In
most paint programs, when you draw a line you see what is called the rubber
band effect. Like a rubber band, the line will stretch to your cursor until you
release it. Program Java1524.java in figure 15.43 will allow you to draw lines
with this rubber band effect. Most of you will find this more natural.
Figure 15.43
// Java1524.java
// This program draws a straight line from the point where the mouse is clicked
// to the point where the mouse is released. In this example the line is
// constantly visible. This is sometimes called the "rubber band" effect.
import java.applet.Applet;
import java.awt.*;
public class Java1524 extends Applet
{
int startX,startY,endX,endY;
public void paint(Graphics g)
{
Expo.drawLine(g,startX,startY,endX,endY);
}
public boolean mouseDown(Event e, int x, int y)
{
startX = x;
startY = y;
return true;
}
public boolean mouseDrag(Event e, int x, int y)
{
endX = x;
endY = y;
repaint();
return true;
}
}
Chapter XV
Intermediate Graphics
587
Figure 15.43 Continued
Again, remember that you cannot truly appreciate the output of the programs in
this chapter unless you are executing them yourself on your computer.
The way program Java1524.java works is by adding the mouseDrag method.
mouseDown is still used to determine the start of the line, and mouseUp still
determine the end. mouseDrag is used to display the line as the mouse is
moving.
One thing you may have noticed about the last 2 programs is that you can only
draw one line. You may have noticed that the magical method update was not
present. Well, what would happen if method update were used? Program
Java1525.java, in figure 15.44, answers this question by essentially adding
method update to what was program Java1524.java.
588
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.44
// Java1525.java
// This program shows that method "update" can causes a peculiar "side effect" in some cases.
// Watch what happens when you try to draw a line.
import java.applet.Applet;
import java.awt.*;
public class Java1525 extends Applet
{
int startX,startY,endX,endY;
public void paint(Graphics g)
{
Expo.drawLine(g,startX,startY,endX,endY);
}
public boolean mouseDown(Event e, int x, int y)
{
startX = x;
startY = y;
return true;
}
public boolean mouseDrag(Event e, int x, int y)
{
endX = x;
endY = y;
repaint();
return true;
}
public void update(Graphics g) { paint(g); }
}
Chapter XV
Intermediate Graphics
589
Here we see the side effect that can be caused by method update. Do you
understand why this is happening? When the update method is present, the
computer does not clear the applet window with each repaint. This means the
old lines are never erased and they all show up on the screen. Some of you may
find this a neat effect. It is possible to cure this side effect, but that requires
programming skills beyond what is taught in the first year computer science
course. This chapter is Intermediate Graphics. Next year, those of you who go
on to AP Computer Science may figure out the cure when you study the chapter
on Advanced Graphics.
Drawing Rectangles
For the next program, we are going to make 2 small changes. First, we will
remove method update. Second, we will change the drawLine command to
drawRectangle. Execute program Java1526.java in figure 15.45, and see what
happens.
Figure 15.45
// Java1526.java
// This program is almost identical to Java1524.java.
// The only difference is that "drawLine" has been changed to "drawRectangle".
// Note how the rectangles are draw with the same "rubber band effect" as the lines.
import java.applet.Applet;
import java.awt.*;
public class Java1526 extends Applet
{
int startX,startY,endX,endY;
public void paint(Graphics g)
{
Expo.drawRectangle(g,startX,startY,endX,endY);
}
public boolean mouseDown(Event e, int x, int y)
{
startX = x;
startY = y;
return true;
}
public boolean mouseDrag(Event e, int x, int y)
{
endX = x;
endY = y;
repaint();
return true;
}
}
590
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.45 Continued
Drawing Circles
Program Java1527.java, in figure 15.46, will deal with drawing circles. This is
much more complicated that drawing lines or rectangles from a programming
point of view. Think of what you need to do to draw a circle with a paint
program. You use your cursor to find the center of the circle and press down the
button. Instead of calling this location (startX, startY) we will call it (centerX,
centerY). As you drag the mouse you make the circle larger as you increase its
radius and then release the button when finished. Since the radius is the distance
from the center to any point on the rim of the circle, we will call the release point
(rimX, rimY) instead of (endX, endY).
Well, we have 2 points just like we did for the lines and the rectangles. In the
case of the circle we need to do a little math. The radius will be the distance
between these 2 points. The math required to compute this is explained below. If
you are in a higher-level math class you should recognize the Pythagorean
Theorem and the distance formula. If not, just accept that I had to write a special
getRadius method for this to work and the method is based on the following
mathematical information:
Chapter XV
Intermediate Graphics
591
c
a
b
Given that the triangle above is a right triangle, if you know the lengths of sides
a and b you can compute side c this formula:
𝑐 = √𝑎 2 + 𝑏 2
This formula is used to find the distance between any 2 points (x1,y1) and
(x2,y2):
𝑑𝑖𝑠𝑡𝑎𝑛𝑐𝑒 = √(𝑥2 − 𝑥1 )2 + (𝑦2 − 𝑦1 )2
Figure 15.46
// Java1527.java
// This program will draw circles using a special "getRadius" method
// which is based on the Pythagorean Formula.
import java.applet.Applet;
import java.awt.*;
public class Java1527 extends Applet
{
int centerX,centerY,rimX,rimY;
public void paint(Graphics g)
{
int radius = getRadius(centerX,centerY,rimX,rimY);
Expo.drawCircle(g,centerX,centerY,radius);
}
592
Exposure Java 2012, PreAPCS Edition
05-31-12
public boolean mouseDown(Event e, int x, int y)
{
centerX = x;
centerY = y;
return true;
}
public boolean mouseDrag(Event e, int x, int y)
{
rimX = x;
rimY = y;
repaint();
return true;
}
public int getRadius(int x1, int y1, int x2, int y2)
{
double radius = Math.sqrt( Math.pow(x2-x1,2) + Math.pow(y2-y1,2) );
return (int) radius;
}
}
Figure 15.46 Continued
Chapter XV
Intermediate Graphics
593
15.8 Creating Clickable Areas in the Applet
There is something that computer mouse users take for granted. It is the ability of
the program to know that a mouse has clicked inside some area. We click on a
color in a paint program. We click on some icon. We click on the top bar of a
window. In each case clicking is not equal to some specified coordinate location.
Rather some action results from clicking anywhere in a specified area.
Program Java1528.java, in figure 15.47, displays three colored squares. The
mission of the program is to see if the program can tell if the mouse is clicked
anywhere in one of the three squares or anywhere outside the squares. This
program includes some new concepts that will be shown separately. Look at the
program in its entirety first with its execution and then more explanation follows.
Figure 15.47
// Java1528.java
// This uses the <Rectangle> class with the <inside> method to determine
// if a certain rectangular area of the screen has been clicked.
import java.applet.Applet;
import java.awt.*;
public class Java1528 extends Applet
{
Rectangle red, green, blue;
int numColor;
public void init()
{
red = new Rectangle(100,75,150,150);
green = new Rectangle(100,275,150,150);
blue = new Rectangle(100,475,150,150);
numColor = 0;
}
public void paint(Graphics g)
{
Expo.setColor(g,Expo.red);
Expo.fillRectangle(g,100,75,250,225);
Expo.setColor(g,Expo.green);
Expo.fillRectangle(g,100,275,250,425);
Expo.setColor(g,Expo.blue);
Expo.fillRectangle(g,100,475,250,625);
Expo.setFont(g,"Arial",Font.BOLD,28);
switch (numColor)
{
case 1:
Expo.setColor(g,Expo.red);
g.drawString("Mouse clicked inside red",300,150);
break;
case 2:
Expo.setColor(g,Expo.green);
g.drawString("Mouse clicked inside green",300,350);
break;
case 3:
Expo.setColor(g,Expo.blue);
g.drawString("Mouse clicked inside blue",300,550);
594
Exposure Java 2012, PreAPCS Edition
05-31-12
break;
case 4:
Expo.setColor(g,Expo.black);
g.drawString("Mouse clicked outside the colored squares",300,40);
break;
}
}
public boolean mouseDown(Event e, int x, int y)
{
if(red.inside(x,y))
numColor = 1;
else if(green.inside(x,y))
numColor = 2;
else if(blue.inside(x,y))
numColor = 3;
else
numColor = 4;
repaint();
return true;
}
}
Figure 15.47 Continued
Java1528.java – Initial Output
Chapter XV
Intermediate Graphics
595
Figure 15.47 Continued
596
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.47 Continued
Chapter XV
Intermediate Graphics
597
Now that you have had a chance to see what the program looks like and how it
behaves, let us break it apart and start understanding the separate pieces. A good
place to start is the init method, shown in figure 15.48.
Figure 15.48
Rectangle red, green, blue;
public void init()
{
red = new Rectangle(100,75,150,150);
green = new Rectangle(100,275,150,150);
blue = new Rectangle(100,475,150,150);
numColor = 0;
}
The Rectangle class is a new class. Do not confuse this class with methods
drawRectangle or fillRectangle. The Rectangle class does not actually draw
anything on the screen. Instead it defines a rectangular area on the screen. Once
defined, we have the ability to see if the mouse is clicked inside this rectangular
area. In effect, we have created something like a button to click on.
Figure 15.49 helps to clarify the purpose of the three Rectangle objects. The
Rectangle class provides the very useful method inside, which determines if a set
of coordinates are inside the dimensions of the Rectangle object. You see yet
another example of the mouseDown event. In this case the coordinate values
provided when the event is triggered determine if the mouse is clicked inside any
of the three squares or outside any of the three squares. Variable numColor is
assigned a color appropriate to the mouse-click location that will be used when
paint method is called.
Figure 15.49
public boolean mouseDown(Event e, int x, int y)
{
if(red.inside(x,y))
numColor = 1;
else if(green.inside(x,y))
numColor = 2;
else if(blue.inside(x,y))
numColor = 3;
else
numColor = 4;
repaint();
return true;
}
598
Exposure Java 2012, PreAPCS Edition
05-31-12
Finally, we look at the paint method in figure 15.50, to see the exciting
conclusion of the Rectangle class program. You may easily say that the three
rectangles are hardly abstract. You can see them in three colors. That is true, but
you are not seeing any of the Rectangle objects. Method paint starts with three
calls to the fillRectangle method, which results in displaying rectangles with the
same dimensions as the red, green and blue objects. This essentially gives the
user something to click on. The switch control structure is used to display the
appropriate message based on the color value of numColor.
Figure 15.50
public void paint(Graphics g)
{
Expo.setColor(g,Expo.red);
Expo.fillRectangle(g,100,75,250,225);
Expo.setColor(g,Expo.green);
Expo.fillRectangle(g,100,275,250,425);
Expo.setColor(g,Expo.blue);
Expo.fillRectangle(g,100,475,250,625);
Expo.setFont(g,"Arial",Font.BOLD,28);
switch (numColor)
{
case 1:
Expo.setColor(g,Expo.red);
g.drawString("Mouse clicked inside red",300,150);
break;
case 2:
Expo.setColor(g,Expo.green);
g.drawString("Mouse clicked inside green",300,350);
break;
case 3:
Expo.setColor(g,Expo.blue);
g.drawString("Mouse clicked inside blue",300,550);
break;
case 4:
Expo.setColor(g,Expo.black);
g.drawString("Mouse clicked outside the colored squares",300,40);
break;
}
}
You may not really quite get this abstract business. Perhaps with program
Java1529.java, in figure 15.51, you will appreciate that objects red, green and
Chapter XV
Intermediate Graphics
599
blue are true abstract rectangles. The next program example is almost identical to
program Java1528.java, but the three fillRectangle statements have been deleted
from the paint method.
Figure 15.51
// Java1529.java
// This program proves that objects of the <Rectangle> class are abstract to the viewer and
// not visible. The three square are intentionally not displayed. The program still works
// like the previous program, but you must guess at the location of the squares.
import java.applet.Applet;
import java.awt.*;
public class Java1529 extends Applet
{
Rectangle red, green, blue;
int numColor;
public void init()
{
red = new Rectangle(100,75,150,150);
green = new Rectangle(100,275,150,150);
blue = new Rectangle(100,475,150,150);
numColor = 0;
}
public void paint(Graphics g)
{
// Note: The solid colored squares are not drawn this time.
Expo.setFont(g,"Arial",Font.BOLD,28);
switch (numColor)
{
case 1:
Expo.setColor(g,Expo.red);
g.drawString("Mouse clicked inside red",300,150);
break;
case 2:
Expo.setColor(g,Expo.green);
g.drawString("Mouse clicked inside green",300,350);
break;
case 3:
Expo.setColor(g,Expo.blue);
g.drawString("Mouse clicked inside blue",300,550);
break;
case 4:
Expo.setColor(g,Expo.black);
g.drawString("Mouse clicked outside the colored squares",300,40);
break;
}
}
public boolean mouseDown(Event e, int x, int y)
{
if(red.inside(x,y))
numColor = 1;
else if(green.inside(x,y))
numColor = 2;
else if(blue.inside(x,y))
numColor = 3;
else
numColor = 4;
repaint();
return true;
}
}
600
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.51 Continued
Java1529.java – Initial Output
Chapter XV
Intermediate Graphics
601
Figure 15.51 Continued
602
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.51 Continued
Note that even though there are no solid color squares visible on the screen, the
Rectangle objects are still there. These invisible defined areas of the screen can
still be clicked even though there is nothing visible to click on. Do keep in mind
that to expect a user to click on some empty area of the screen in order for
something to happen is not user-friendly at all. If you expect the user to click
somewhere, draw something there for them to click on.
Rectangle Object Parameters
Before we go on we need to clarify something. You probably noticed that
defining a Rectangle object requires four int parameters. The methods
drawRectangle and fillRectangle also require four int parameters. What must
be understood is the four int parameters have a different meaning when creating
Rectangle objects.
An example of drawRectangle would be Expo.drawRectangle(g,x1,y1,x2,y2);
(x1,y1) represent the upper-left-hand corner of the rectangle. (x2,y2) represent
the lower-right-hand corner as is shown in Figure 15.52.
Chapter XV
Intermediate Graphics
603
Figure 15.52
When an object of the Rectangle class is constructed, the parameters are
different. Here is another example:
Rectangle area = new Rectangle(x,y,width,height);
The first 2 parameters (x,y) are still the upper-left-hand corner of the rectangle.
The difference is the lower-right-hand corner is NOT used at all. Instead, the 3rd
parameter us the width of the rectangle, and the 4th parameter is the height.
Figure 15.53 gives a visual example of this:
Figure 15.53
In the past couple sections, you have seen several pieces of a paint program, but
not an entire paint program with everything put together. There are 2 reasons for
this. First, such a program would be too complicated for this first year class.
Second, a paint program is sometimes an assignment in AP Computer Science.
604
Exposure Java 2012, PreAPCS Edition
05-31-12
15.9 Computer Animation
Computer Animation makes many of today’s modern movies possible. It also has
been making video games possible for decades. The ability to move things on the
screen makes your program much more dynamic and exciting. We are going to
conclude this chapter, as well as your textbook, by going through a series of 8
programs. The goal is to make a circle move across the screen. We will not
achieve this on the first program, but each program will get closer.
Do keep in mind that now, more than ever, you need to be executing these
programs on your computer to see the output. It is impossible to show animated
output in a textbook. I will be able to show the output of the first 3 programs
since those do not have animation yet.
Program Java1530.java, in figure 15.54, is our first step in the animation journey.
Figure 15.54
// Java1530.java Animation Part 1
// This program simply draws a solid black circle.
// This will eventually be "animated" as we go through the next few programs.
import java.awt.*;
public class Java1530 extends java.applet.Applet
{
public void paint(Graphics g)
{
Expo.fillCircle(g,50,325,25);
}
}
Chapter XV
Intermediate Graphics
605
You may be wondering why Java1530.java does nothing more than draw a
circle. Here is why. Students get very excited when they do their final graphics
project. The especially get excited when animation becomes involved. The
following conversation occurs several times each year:
Eager Student:
Mr. Schram, my project is going to be so awesome! I am going
to have this move that way and that move this way and this will
be doing this and that will be doing that…
Mr. Schram:
That sounds great. What do you have on the screen so far?
Eager Student:
Nothing. I have not figured out animation yet.
Here is my point. You cannot animate something if you do not have something to
start with. If I want to animate a circle, I start by drawing a circle.
Program Java1531.java, in figure 15.55, shows our first step. To make a circle
look like it is moving across the screen, I need to draw it at different positions
across the screen. I will draw the circle 10 times, once at the original location
where the X-value is 50, then again at the X-values of 150, 250, 350, 450, 550,
650, 750, 850 and 950.
Figure 15.55
// Java1531.java Animation Part 2
// This program simply draws the solid black circle at 10 different locations.
// This is not yet animation because we see all 10 circles at the same time.
import java.awt.*;
public class Java1531 extends java.applet.Applet
{
public void paint(Graphics g)
{
Expo.fillCircle(g,50,325,25);
Expo.fillCircle(g,150,325,25);
Expo.fillCircle(g,250,325,25);
Expo.fillCircle(g,350,325,25);
Expo.fillCircle(g,450,325,25);
Expo.fillCircle(g,550,325,25);
Expo.fillCircle(g,650,325,25);
Expo.fillCircle(g,750,325,25);
Expo.fillCircle(g,850,325,25);
Expo.fillCircle(g,950,325,25);
}
}
606
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.55 Continued
The output of program Java1531.java is hardly animation, but it shows
something. There are 10 positions that I want my circle to take. The problem is I
am seeing the circle at all 10 of those positions at the same time. Program
Java1532.java, in figure 15.56, attempts to deal with this problem by erasing
each circle before the next circle is drawn.
Figure 15.56
// Java1532.java Animation Part 3
// This program erases every circle before it draws the next one.
// This is necessary for animation; however, the process happens so fast you cannot see the circle move.
import java.awt.*;
public class Java1532 extends java.applet.Applet
{
public void paint(Graphics g)
{
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,50,325,25);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,50,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,150,325,25);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,150,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,250,325,25);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,250,325,25);
Chapter XV
Intermediate Graphics
607
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,350,325,25);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,350,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,450,325,25);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,450,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,550,325,25);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,550,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,650,325,25);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,650,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,750,325,25);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,750,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,850,325,25);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,850,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,950,325,25);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,950,325,25);
}
}
Figure 15.56 Continued
608
Exposure Java 2012, PreAPCS Edition
05-31-12
In the animation journey it looks like we have taken a giant step backwards. The
output of program Java1532.java shows absolutely nothing. It may not look like
it, but the program did make the circle move across the screen. The problem is it
moved so quickly, you did not get a chance to see it. Program Java1533.java, in
figure 15.57 cures this problem by adding some Expo.delay commands. We need
the image to stay on the screen long enough for your eyes to have a chance to see
it. It does not need to be long, even a small fraction of a second is fine. The
delay method has a single parameter which indicates the number of milliseconds
that the computer should wait. A delay of 1000 would be 1 second. A delay of
2000 would be 2 seconds. A delay of 500 would be ½ a second.
This will be the first program that actually shows animation. Because of this, we
cannot show you the output in the textbook. You will have to execute the
remaining programs on your computer to see what is happening.
Figure 15.57
// Java1533.java Animation Part 4
// This program adds a short 1 second delay after each circle is drawn
// to give you a chance to see it before it is erased.
import java.awt.*;
public class Java1533 extends java.applet.Applet
{
public void paint(Graphics g)
{
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,50,325,25);
Expo.delay(1000);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,50,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,150,325,25);
Expo.delay(1000);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,150,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,250,325,25);
Expo.delay(1000);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,250,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,350,325,25);
Expo.delay(1000);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,350,325,25);
Chapter XV
Intermediate Graphics
609
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,450,325,25);
Expo.delay(1000);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,450,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,550,325,25);
Expo.delay(1000);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,550,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,650,325,25);
Expo.delay(1000);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,650,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,750,325,25);
Expo.delay(1000);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,750,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,850,325,25);
Expo.delay(1000);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,850,325,25);
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,950,325,25);
Expo.delay(1000);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,950,325,25);
}
}
Yes, we have achieved animation. It may not have been earth-shattering
animation, but the ball did move across the screen. You probably noticed the
program is very repetitive. In program Java1533.java there are 10 groups of 5
line code segments. The only thing that is different in each group is the X-value
of the circle. In the first group this value is 50. In the last group the value is 950.
You should see that as you go from one group to the next the value increases by
100. Now, think back. We have something repetitive that counts from 50 to 950
by 100. This is ideal for a for loop. Program Java1534.java, in figure 15.58
does the exact same thing as program Java1533.java, but now a for loop is used
and the program is much shorter.
610
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.58
// Java1534.java Animation Part 5
// This program has the same output as the previous program.
// The program is now much shorter since a for loop is used.
import java.awt.*;
public class Java1534 extends java.applet.Applet
{
public void paint(Graphics g)
{
for (int x = 50; x <= 950; x+=100)
{
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,x,325,25);
Expo.delay(1000);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,x,325,25);
}
}
}
You have probably noticed the movement of the last 2 programs was a little
choppy. It resembles the animation of a cheap cartoon. You may also have seen
animated movies where the animation is much smoother and far superior. What
makes the difference? Think of a film strip. There are 24 frames for every 1
second of film. When a live action movie is filmed, the video camera takes 24
distinct pictures per second. In a made-for-the-screen animated movie, the
animators actually draw 24 distinct pictures for every 1 second of film. This is
129,600 pictures for a 90 minute movie. This is why animated movies take 5-7
years to create.
Now think of a cheap 30 minute cartoon TV show. There is no way they are
going to put in the same amount of effort when they have to mass produce as
many as 65 episodes per season. For these cartoons, the animators only draw 4
distinct pictures for every 1 second of film. Each picture is duplicated on 6
frames in a row. This makes the animation look far less smooth.
Program Java1535.java, in figure 15.59 improves the quality of the animation by
increasing the number of circles drawn. Instead of the circle moving 100 pixels at
a time, it will only move 10. The delay is changed from 1000 to 100 to
compensate. We are now drawing 10 times as many circles, each of which is on
the screen for 1/10 the amount of time as before. Execute the program and you
should see smoother animation.
Chapter XV
Intermediate Graphics
611
Figure 15.59
// Java1535.java Animation Part 6
// This program makes the animation smoother by using a smaller delay
// and a smaller increment in the for loop.
import java.awt.*;
public class Java1535 extends java.applet.Applet
{
public void paint(Graphics g)
{
for (int x = 50; x <= 950; x+=10)
{
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,x,325,25);
Expo.delay(100);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,x,325,25);
}
}
}
Now you might ask, “If changing the increment from 100 to 10 made the
animation look better, would changing it from 10 to 1 make the animation look
even better than that?” Execute program Java1536.java, in figure 15.60 and see
for yourself. Note, the delay is reduced again to compensate.
Figure 15.60
// Java1536.java Animation Part 7
// This program makes the animation as smooth as possible by having an increment of
// just 1 pixel in the for loop. The delay is also made smaller.
import java.awt.*;
public class Java1536 extends java.applet.Applet
{
public void paint(Graphics g)
{
for (int x = 50; x <= 950; x+=1)
{
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,x,325,25);
Expo.delay(10);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,x,325,25);
}
}
}
612
Exposure Java 2012, PreAPCS Edition
05-31-12
The answer is “Yes.” We now have the circle moving as smooth as possible. You
may have noticed the circle flickering as it was moving. This is a side effect of
the draw-and-erase style of animation that we are using. If you have ever played
your parent’s really, really old video game system, you might have noticed the
characters flicker in a similar manner. That is because the old video game
systems used this simplistic form of animation. You probably also know that this
flickering does not occur in modern video games. What is different? Modern
video games use a completely different form of animation which is more
complicated and not taught in this course. It is taught at the end of AP Computer
Science so some of you may learn it next year.
Program Java1537.java, in figure 15.61, draws 3 circles at a time instead of just
one. The result will be a snowman moving across the screen. This program will
have even more flickering. You may be able to minimize the flickering by
making the delay longer, but if you make it too long the snowman may move too
slowly. Keep in mind that the flickering side effect, will not cause you to lose
points on your final graphics project.
Figure 15.61
// Java1537.java Animation Part 8
// This program draws and erases 3 circles instead of one to animate a snowman
// across the screen. The flickering that you will see is normal for this type of animation.
// In AP Computer Science you will learn a more advanced type of animation that
// eliminates the flicker.
import java.awt.*;
public class Java1537 extends java.applet.Applet
{
public void paint(Graphics g)
{
for (int x = 50; x <= 950; x+=1)
{
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,x,290,15);
Expo.fillCircle(g,x,325,25);
Expo.fillCircle(g,x,380,40);
Expo.delay(10);
Expo.setColor(g,Expo.white);
Expo.fillCircle(g,x,290,15);
Expo.fillCircle(g,x,325,25);
Expo.fillCircle(g,x,380,40);
}
}
}
Chapter XV
Intermediate Graphics
613
Figure 15.61 Continued
The final program in this section will be program Java1538.java, in figure 15.62.
This program is similar to the previous one, but instead of drawing 3 circles to
animate a snowman, it uses drawImage to make a bunny move across the screen.
Figure 15.62
// Java1538.java Animation Part 9
// This program shows that an image from a file can also be made to move across the screen.
// As with the snowman, there can be considerable flickering.
import java.awt.*;
public class Java1538 extends java.applet.Applet
{
Image picture;
public void init()
{
picture = getImage(getDocumentBase(),"bunny.png");
}
public void paint(Graphics g)
{
for (int x = -100; x <= 1100; x+=3)
{
g.drawImage(picture,x,200,this);
Expo.delay(30);
Expo.setColor(g,Expo.white);
Expo.fillRectangle(g,x,200,x+100,300);
}
}
}
614
Exposure Java 2012, PreAPCS Edition
05-31-12
Figure 15.62 Continued
Animation with a Multi-Colored Background
The draw-and-erase animation seems simple enough. First, you draw something.
Then, you wait a tiny bit of time. Then, you erase it by drawing over it in the
background color. Then you redraw it in a different location and repeat the
process. OK, but what if your background is not one solid color? What if you
have a multi-colored background? This problem is demonstrated with program
Java1539.java in figure 15.63. The first for loop generates 9 different colored
vertical stripes. The second for loop is used to move the snowman across the
screen. Since the first stripe is red, red is used as the erasing color. When you
execute the program it seems to work at first, but once the snowman gets beyond
the first stripe, the animation ceases to work properly.
Figure 15.63
// Java1539.java Animation Part 10
// This program demonstrates the problem that occurs with a multi-colored background.
import java.awt.*;
public class Java1539 extends java.applet.Applet
{
Chapter XV
Intermediate Graphics
615
public void paint(Graphics g)
{
for (int c = 1; c <= 9; c++)
{
Expo.setColor(g,c);
Expo.fillRectangle(g, (c-1)*111, 0, c*111, 650);
}
for (int x = 50; x <= 950; x+=3)
{
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,x,290,15);
Expo.fillCircle(g,x,325,25);
Expo.fillCircle(g,x,380,40);
Expo.delay(30);
Expo.setColor(g,Expo.red);
Expo.fillCircle(g,x,290,15);
Expo.fillCircle(g,x,325,25);
Expo.fillCircle(g,x,380,40);
}
}
}
Figure 15.63 Continued
616
Exposure Java 2012, PreAPCS Edition
05-31-12
To fix this problem we need to use something other than draw-and-erase
animation. There is a different type of animation which I will call draw-andredraw. In this type of animation nothing gets erased. Instead, the entire
background gets redrawn every time the object moves. This is demonstrated with
program Java1540.java in figure 15.64. You should notice two big differences
between this program and Java1539.java. First, the for loop that generates the
background is now inside the for loop that moves the snowman. Second, the
snowman is never erased. Every time the snowman moves the entire background
is drawn on top of him.
Note: This type of animation has the potential for serious flickering, especially
with complicated backgrounds.
Figure 15.64
// Java1540.java Animation Part 11
// This program shows how to handle a multi-colored background.
// Instead of "draw-and-erase", it is "draw-and-redraw".
// The entire background is redrawn every time the object moves.
// NOTE: This does have the potential for serious flickering.
import java.awt.*;
public class Java1540 extends java.applet.Applet
{
public void paint(Graphics g)
{
for (int x = 50; x <= 950; x+=3)
{
for (int c = 1; c <= 9; c++)
{
Expo.setColor(g,c);
Expo.fillRectangle(g, (c-1)*111, 0, c*111, 650);
}
Expo.setColor(g,Expo.black);
Expo.fillCircle(g,x,290,15);
Expo.fillCircle(g,x,325,25);
Expo.fillCircle(g,x,380,40);
Expo.delay(30);
}
}
}
Chapter XV
Intermediate Graphics
617
Figure 15.64 Continued
15.10 The Last Word
The final section in this graphics chapter actually has nothing to do with graphics
at all. This is the final section of the final chapter of this textbook, and there is
one last point I want to make – and now you are ready to understand it.
Some people may be concerned that with technology changing so rapidly, the
programming knowledge that they have acquired in this course will soon be out of
date. While new programming languages pop up from time to time, the logic of
programming has never changed.
The next three programs all do the exact same thing. The first is written in Java.
The second in C++ and the third in Pascal. Even though you may have never seen
C++ or Pascal, you may be surprised how familiar these programs will look to
you now that you know Java.
618
Exposure Java 2012, PreAPCS Edition
05-31-12
Program Java1541.java, in figure 15.65 shows nothing new. There is a for loop
that counts backwards from 20 down to 0. Inside the for loop is an if…else
structure that checks if dividing the loop counter by 2 gives you a remainder of 0.
Based on this it will tell you if the number is even or odd. The intent is not to
teach any new material here. You learned about control structures some time
ago. The intent is to have you compare this program to the next two.
Figure 15.65
// Java1541.java
// This program will count backwards from 20 to 0 and displays which numbers
// are even and which are odd.
// Compare this Java code to the code from other languages.
public class Java1541
{
public static void main (String args[])
{
System.out.println("\nJAVA1539.JAVA\n\n");
for (int j = 20; j >= 0; j--)
{
if (j % 2 == 0)
{
System.out.println(j + " is an even number.");
}
else
{
System.out.println(j + " is an odd number.");
}
}
System.out.println();
}
}
Chapter XV
Intermediate Graphics
619
Now look at program CPlusPlus.CPP, in figure 15.66. This is the same program
written in C++. Even though you may have never seen a C++ program before,
you might be surprised just how familiar the program will look, even though it is
in a different language. Well… mostly different. Java did get its control
structures from C++. The for loop and the if…else structure, and even the
comments are identical.
Figure 15.66
// CPlusPlus.CPP
// This program will count backwards from 20 to 0 and displays which numbers
// are even and which are odd.
// Compare this C++ code to the code from other languages.
#include <iostream.h>
#include <conio.h>
void main()
{
cout << endl << "CPlusPlus.CPP" << endl << endl;
for (int j = 20; j >= 0; j--)
{
if (j % 2 == 0)
{
cout << j << " is an even number." << endl;
}
else
{
cout << j << " is an odd number." << endl;
}
}
cout << endl;
getch(); // makes the computer wait until a character is pressed
}
620
Exposure Java 2012, PreAPCS Edition
05-31-12
And finally, look at program Pascal.PAS, in figure 15.67. This is the same
program written in Pascal. The point being made with these 3 programs is while
the syntax is different with different languages, the logic is the same. To display
text, Java uses System.out.println. C++ uses cout and Pascal uses WRITELN.
Braces { } mark the beginning and ending of blocks in Java and C++. In Pascal
braces are used for comments. The actual words BEGIN and END are used
instead.
Figure 15.67
{ Pascal.PAS
This program will count backwards from 20 to 0 and displays which numbers
are even and which are odd.
Compare this Pascal code to the code from other languages. }
PROGRAM My_Pascal_Program;
VAR
J : INTEGER; (* Loop Counter *)
BEGIN
WRITELN;
WRITELN('Pascal.PAS');
WRITELN;
FOR J := 20 DOWNTO 0 DO BEGIN
IF J MOD 2 = 0 THEN BEGIN
WRITELN(J,' is an even number.')
END
ELSE BEGIN
WRITELN(J,' is an odd number.')
END
END
END.
I will use one final example to emphasize this point. At John Paul II High School,
we have a religion teacher who is known as “Sister Peggy”. In 2007, Sister Peggy
came by my classroom to drop something off and noticed the assignment my
students were doing. “Oh, they are learning the for loop” she said. I was a little
surprised until I learned that Sister Peggy taught Computer Science back in the
1970s. Back then, she taught the language FORTRAN. While FORTRAN is very
different from Java, the logic is still the same. Programming knowledge will
never become obsolete.
Chapter XV
Intermediate Graphics
621
622
Exposure Java 2012, PreAPCS Edition
05-31-12