Unit2 - Graphics New
Unit2 - Graphics New
Edited by Shane Torbert with contributions from Sally Bellacqua under the direction of Jerry Berry supported in part by the Links Project Thomas Jefferson High School for Science and Technology
Unit2
Java
Two-2
Java
Unit2
Copyright Information These materials are copyright 2000-2003 by the author; additional contributions from Marion Billington, Charles Brewer, Margie Cross, Cathy Eagen, Anne Little, John Mitchell, John Myers, Steve Rose, John Totten, Ankur Shah, and Greg W. Price. All rights not explicitly granted below are reserved. You are encouraged to reproduce these materials in whole or in part for use within your educational institution provided appropriate credit is given. You may distribute these materials to other institutions or representatives thereof only if the entire work is transferred in its complete, unaltered form, either as the original Microsoft Word files or as an original, high quality printout. Suns Java 2 SDK, Standard Edition, version 1.4.1 can be found at http://java.sun.com/j2se/1.4. Auburns pcGRASP can be found at http://www.eng.auburn.edu/department/csse/research/research_groups/grasp. The free FCPS Computer Science CD, with software and materials, is edited by Steve Rose (srose@lan.tjhsst.edu). You may alter these materials to suit your needs and distribute these altered materials within your educational institution provided that appropriate credit is given and that the nature of your changes is clearly indicated. You may not distribute altered versions of these materials to any other institution. If you have any questions about this agreement please e-mail mr@torbert.com.
Two-3
Unit2
Java
Two-4
Java
Unit2
Discussion
Each of your driver programs will create a frame. You will add a panel to each frame. Any panel class you write will inherit from JPanel. For instance, Panel00 extends JPanel. JPanel Panel00 So Panel00 isa JPanel isa JComponent isa Container isa Component isa Object. Imagine each panel as a canvas on which you will paint and note that a frame is able to hold panels because each frame is also a container. Eventually we will use a panels container ability, too. Panel Panel on a Frame
(0,0)
The coordinate system treats the upper-left corner of the panel as (0, 0). As you move horizontally to the right the x-values increasethis should be exactly as you are accustomed. As you move vertically down the y-values increasethis should be exactly backwards from what you are accustomed. The reason the origin is placed at the upper-left corner rather than the lower-left corner is so that the origin remains fixed even when the user resizes the frame. Users typically manipulate the bottom-right corner in order to resize a frame.
Two-5
Unit2
Java
Lab00
Hello World
Objective The difference between a driver and a resource. Background Documentation for Java Foundation Classes is maintained by Sun Microsystems. The API is available on-line. Ask your teacher how to access this information on your system. Specification Filenames Unit2\Lab00\Driver00.java and Unit2\Lab00\Panel00.java. Enter the source code shown below, then compile and run the program. Note that the panel is just a resource. Do not run the panel. Run the driver. Line 1: Import swing classes from the javax.swing package. Swing class names begin with J. Line 4: Need a main to run. Line 6: Our frame object. Line 10: Content arrives on the screen via our panel object. Line 11: The panel objects paintComponent method is automatically called. Line 2: Toolkit. Abstract Windowing
Line 3: Inherit from JPanel. Line 5: Override paintComponent. Line 7: Calls the original paintComponent. Line 9-14: Graphics commands. A DOS window and a frame open to display the program. After execution, close the frame by clicking the X, then press CTRL-C to close DOS (do not X the DOS window). Be careful! Java is very picky. Make sure you save both files in the same folder, Unit2\Lab00. Test Data Two-6
Java
Unit2
Go to www.tjhsst.edu/compsci.
Exercises
Lab00
Complete this scavenger hunt using Suns on-line Java API. 1) How many interfaces does JPanel implement? _________________________
10) Why should you not use the method getClipRect? _________________________
Two-7
Unit2
Java
Discussion
Graphics Commands
The (x, y) coordinates you pass to the method drawString specify the point shown below. For any font, the height of the big rectangle is called the height, the height of the middle rectangle is called the ascent, the height of the lower rectangle is called the descent, and the height of the upper rectangle is called the leading.
(x, y)
yS
baseline
The (x, y) coordinates you pass to other drawing methods specify the upper-left corner of the figure being drawn. The result of a fillOval method is shown here: (x, y)
The third and fourth arguments represent the width and height of the dotted-rectangle. The one exception to this is drawLine, where both pairs specify points to be connected. The following shapes can be drawn: Shape to be drawn Rectangle Square Ellipse Circle Point (Pixel) Line Polygon Polyline Example command g.drawRect(25, 50, 100, 75); g.drawRect(25, 50, 75, 75); g.drawOval(25, 50, 100, 75); g.drawOval(25, 50, 75, 75); g.drawRect(25, 50, 0, 0); g.drawLine(25, 50, 100, 75); //Note: (100,75)=(x2,y2) g.drawPolygon(xPoints, yPoints, num); g.drawPolyline(xPoints, yPoints, num);
Note again that drawLine does not give the diagonal of the dotted-rectangle shown above. The four arguments represent the (x, y) coordinates of the two endpoints of the line (not the width and height). Note also that the value of num must be the number of points that make up the polygon or polyline. This value will be equal to the length of each array xPoints and yPoints. The difference in these two commands is that a polygon automatically connects the last point back to the first; a polyline does not. Be careful! The order of the points for a polygon makes a difference. For instance: P0 P1 P0 P1
P2 Two-8
P3 P2 3
Java
Unit2
Lab01
Welcome Home
Objective Graphics commands. Background There are thirteen pre-defined colors in the Color class: black, blue, cyan, darkGray, gray, green, lightGray, magenta, orange, pink, red, white, and yellow. To set the color to red, a darker shade of red, or a brighter shade of red: g.setColor(Color.red); g.setColor(Color.red.darker()); g.setColor(Color.red.brighter()); If you want a customized color: g.setColor(new Color(red, green, blue)); Here red, green, and blue are each integers from 0 to 255 (inclusive). On-line color charts are available to help you determine these values. Ask your teacher how to access these charts on your system. There are three different styles of font in the Font class: plain, bold, and italic. To set a plain or bold font: g.setFont(new Font("Serif", Font.PLAIN, 8)); g.setFont(new Font("Serif", Font.BOLD, 8)); To set an italicized font or a bold and italicized font: g.setFont(new Font("SansSerif", Font.ITALIC, 8)); g.setFont(new Font("Monospaced", Font.BOLD | Font.ITALIC, 8)); Not all fonts work. Safe fonts are Serif (fancy), SansSerif (regular), and Monospaced (block-letters). Specification Filename Unit2\Lab01\Driver01.java. You may save Driver00.java as Driver01.java and modify the file. A suggested size for the frame is included with the on-line demo. Add a panel object of type Panel01. Filename Unit2\Lab01\Panel01.java. You may save Panel00.java as Panel01.java and modify the file. Use graphics commands to draw the house shown in the on-line demo. You may approximate colors and coordinates but note that the panel is smaller than the frame. If you set the frames size to 400x325 the panel will not be 400x325. The frame includes a title bar and a border that take up some of the space. Be careful! Make sure you save to the Unit2\Lab01 folder. Test Data Go to www.tjhsst.edu/compsci.
Two-9
Unit2
Java
Exercises
Lab01
Complete this scavenger hunt using Suns on-line Java API. 1) What package is Color in? _________________________
Two-10
Java
Unit2
Discussion
indexxPointsyPoints075200117515 02275200 These two arrays represent the following three points: P0 = (75, 200) P1 = (175, 150) P2 = (275, 200) Connected here to draw a triangle.
The drawPolygon method requires integer array arguments specifying (x, y) points. These points are the vertices of the polygon. Notice that shape drawing commands begin with either draw or fill, specifying either an outlined shape or a solid shape.
To draw a series of lines, from (0, 25) to (0, 200), (10, 25) to (10, 200), (20, 25) to (20, 200), , (400, 25) to (400, 200), use the code shown below. Note that the y-values of the endpoints are always 25 and 200. The x-values of the endpoints are always the same number (for each line), and this number increases by 10 with each iteration of the loop. for(int x = 0; x <= 400; x += 10) g.drawLine(x, 25, x, 200); This loop produces x values of 0, 10, 20, 30, , 400. These two lines of code draw the forty-one lines you see on the panel. It is as if we had written out forty-one different drawLine commands, but it only took us two lines of code. Oh, the power of a for-loop.
Lab02
Two-11
Unit2
Java
Objective Loops and images. Background The two most important graphics commands to understand for this lab are fillOval and drawImage. The fillOval method can be used to draw circles. The method requires four arguments. The first two arguments specify the upper-left corner of the rectangle (or square) enclosing the oval (or circle). They do not specify the center of the circle. The last two arguments specify the width and height of the enclosing square. They do not specify the radius of the circle. They specify its diameter. For a circle with center at (x, y) and radius r, use: g.fillOval(x r, y r, 2 * r, 2 * r); Be careful! The machine will not understand 2r. You must write 2 * r. Image files (jpg, jpeg, gif, or png) can be represented as objects: ImageIcon thomas = new ImageIcon("tj.jpg"); For this to work there must be an image file named tj.jpg in your Unit2\Lab02 folder. This image can be displayed with its upper-left corner at (50, 50) using the commands: g.drawImage(thomas.getImage(), 50, 50, null); g.drawImage(thomas.getImage(), 50, 50, 25, 75, null); //scaled image The keyword null represents the absence of an object. A required argument of type ImageObserver, that we are not interested in, must be specified in order to make the method work. Passing null satisfies this requirement. Since drawImage is overloaded, two optional arguments may be use to scale the image. Note how different types of objects work together in order to make the image appear on the screen: ImageIcon object created Image getImage method Graphics drawImage method JPanel appears on the screen
Specification Filename Unit2\Lab02\Driver02.java. Make sure to add a panel object of type Panel02. Filename Unit2\Lab02\Panel02.java. Use graphics commands to draw a framed picture of your schools namesake, principal, or inspirational leader. The previous discussion on polygons and loops contains information that will be helpful in drawing the repeated patterns necessary for the frame effect. Test Data Go to www.tjhsst.edu/compsci.
Two-12
Java
Unit2
Exercises
Lab02
Complete this scavenger hunt using Suns on-line Java API. 1) What package is ImageIcon in? _________________________
2) What interface that begins with the letter I does ImageIcon implement? _______________________
Two-13
Unit2
Java
Discussion
Double Buffering
When a driver runs, a frame is created, a panel is added to the frame, and both are made visible on the screen. The panel appears on the screen by having its paintComponent method called. You have defined this method to display a picture appropriate to each lab. The graphics commands you call from paintComponent draw directly onto the panel. Sometimes it is useful to draw off the screen first. Off-Screen Buffer An image that you draw your picture on using graphics commands. On-Screen Buffer The panel, on which you draw only the image previously drawn off-screen.
We have seen how to draw an image on a panel. Recall: g.drawImage(myImage, x, y, width, height, null); This command draws an image named myImage at position (x, y) with a scaled size of width by height. This image could come from an ImageIcon object, as in thomas.getImage(), or from an image object itself. To create such an image object we will use the class BufferedImage. BufferedImage myImage; myImage = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB); This creates a blank image named myImage. We can edit this image because it is buffered. To edit myImage using drawing commands we must first access its graphics attribute. Graphics buffer = myImage.getGraphics(); Be careful! This is not the same Graphics object that appears as an argument to the method paintComponent. That object draws directly on the panel. This Graphics object does not draw directly on the panel. This object draws on the off-screen image named myImage. All the graphics commands that you know work exactly as you would expect them to, only the picture is drawn onto the image instead of onto the panel. In order to see this picture, you must draw the image onto the panel. public void paintComponent(Graphics g) { g.drawImage(myImage, 0, 0, getWidth(), getHeight(), null); } Note that we do not have to call myImage.getImage() because myImage is itself an image. The methods getWidth() and getHeight() determine the current width and height of the panel. These values may change during runtime as the user resizes the frame. The image will be scaled to fill up the panel, however big or small it may be. There is a shell for Lab03 that has this off-screen buffer already set up for you.
Two-14
Java
Unit2
Lab03
Two-15
Unit2
Java
Exercises
Lab03
Complete this scavenger hunt using Suns on-line Java API. 1) How many fields does the Math class define? _________________________
3) How many non-static methods does the Math class define? _________________________
4) How many void methods does the Math class define? _________________________
5) How many no-argument methods does the Math class define? _________________________
Two-16
Java
Unit2
Discussion
Buckets
Given two water buckets of capacity three and five gallons and an unlimited water supply, you can produce exactly four gallons of water as follows: three gallon bucket 0 3 0 2 2 3 five gallon bucket 5 2 2 0 5 4
1. 2. 3. 4. 5. 6.
Fill the five-gallon bucket. Pour from five into three until three is full. Empty the three-gallon bucket. Pour from five into three until five is empty. Fill the five-gallon bucket. Pour from five into three until three is full.
Each bucket knows how much water it currently holds. This value may be different for two different buckets. The Bucket class defines a field to keep track of the current water level for a bucket. Each bucket has its own copy of this water variable to track its own water level. One buckets water level can change without affecting another bucket. The Bucket class tracks the total water in all buckets in addition to the amount of water in each individual bucket. Use the command: Bucket.useTotal(true); to have the numbers at the top of the window change color based on the total water. public class Bucket { private static int totalWater; private int water; ... } totalWater three water five water 4 3 7 Use the keyword static if there should be only one copy no matter how many object are created. This object diagram shows the end state of the algorithm above. Two different copies of the instance field water are made. Each copy of water can have its own unique value that is unaffected by the other buckets. Only one copy of the static field totalWater is made. If a method affects this field, that change can influence other methods that also access this field.
Only one copy of a static field exists no matter how many objects are created. Consult the Bucket API at www.tjhsst.edu/compsci for the complete Bucket documentation.
Two-17
Unit2
Java
Lab04
Buckets
Objective To understand instance data and static data. Background The program shown here is a demo and not a solution to this lab. This demo implements the algorithm from the Bucket discussion. Since we want to see our program run, a frame is created as usual and a panel is added to the frame. The panel is of type BucketPanel that is already written and should be in your Unit2\Lab04 folder. Once the frame is created, we create the individual bucket objects and set the speed of the animation. We then proceed to solve the actual problem; in this case, we had to produce exactly four gallons. In your solutions to this lab you must produce every possible amount of water for the buckets you are given. Specification Filename Unit2\Lab04\Driver04.java. Create two buckets with capacities of four and seven gallons. Use methods of the Bucket class to turn all the white numbers at the top of the window red. Filename Unit2\Lab04\Driver04_Part2.java. Save your Driver04.java file as Driver04_Part2.java. Track the total water as mentioned in the discussion. Create three buckets with capacities of three, five, and seven gallons. Turn all the white numbers at the top of the window red. Test Data Go to www.tjhsst.edu/compsci. Turn these all red.
Two-18
Java
Unit2
Exercises
Lab04
Solve these bucket problems. 1) Given two buckets named five and six with capacities of five and six, respectively, produce exactly four gallons of water.
2) Given two buckets named four and five with capacities of four and five, respectively, produce exactly two gallons of water.
3) Given two buckets named two and four with capacities of two and four, respectively, produce exactly three gallons of water.
Two-19
Unit2
Java
Discussion
In BucketPanel, the image displayed on the screen is determined each time the panel is repainted by calling Bucket.getImage. Since the timer forces the panel to repaint itself every 10 milliseconds, the image on the screen is refreshed over and over again. Thus, the animation we saw in Lab04 is achieved. We will discuss timers in greater depth in Lab 10.
Two-20
Java
Unit2
Lab05
Bugs
Objective To use documentation to solve a problem. Background Bugs are simplistic objects that know only where they are. Each bug knows where it is by storing its position as two integer variables (points stored only with integers are known as lattice points). These xand y-coordinates are the only data stored by a bug object. Bugs can be created in two different ways. You can either specify a bugs starting position (x and y), or you can specify another bug that already exists whose position this new bug will copy. Bugs are more than happy to tell you where they are. They will reveal their position with the two methods getX and getY, which return a bugs x- and y-coordinate, respectively. Bugs can relate to other bugs in two ways. A bug can tell if it is at the same position as another bug. It does this by asking that bug for its position and comparing those values to its own position. When you call the boolean method sameSpot on a bug and tell it which other bug to compare itself to, the return value of the method is either true or false, indicating whether or not the two bugs are next to each other. A bug can also walk towards another bug. You have to tell the bug which other bug to walk towards and also what percentage of the total distance to travel. Thus, the method walkTowards requires two arguments, one bug and one decimal value representing the percentage of the total distance to travel. Consult the Bug API at www.tjhsst.edu/compsci for the complete Bug documentation. Specification Filename Unit2\Lab05\Driver05.java (load). Create four bugs located in the four corners of your image. So long as any two bugs are not standing at the same position, have each bug walk ten percent of the way towards its clockwise neighbor. At each iteration of this process, draw four lines on the image showing the distance remaining between each pair of neighbors. Test Data Go to www.tjhsst.edu/compsci.
Two-21
Unit2
Java
Exercises
Lab05
Answer these questions about bugs and buckets. Consult the API only when necessary. 1) Tell a bucket named ten to pour its contents into a bucket named zero.
3) Create a bug along the top of the image, 37 pixels to the right of the upper-left corner.
5) Create a bucket named two that has a capacity of three gallons, but dont ever do this again!
6) Tell a bug named pete to walk halfway towards a bug named mary.
7) Why didnt you have to know pete or marys position in Question #6?
8) Why didnt you have to know ten or zeros contents or capacity in Question #1?
9) What principle of computer science was illustrated in Question #7 and Question #8?
10) Give any other example of this principle from the computer science you have studied thus far.
Two-22
Java
Unit2
Discussion
Turtle
In the early 1970s MIT introduced a turtle to the LOGO system. Our Java version of turtle is based on the Logo Writer software. For nostalgia we name our sample turtle smidge. Each turtle stores four pieces of data. Like bugs, turtles have an (x, y) position. Unlike bugs, a turtles position is not restricted to integer values. A turtle also stores its heading, the direction it is currently facing, an angle measured counterclockwise from due east (i.e., zero degrees is to the right). This angle is also stored as a decimal value. Lastly, each turtle carries a magic marker that it uses to draw pretty shapes. Each turtle stores the current color of its magic marker as an object of the Color class. Action Move forward. Move backward. Move backward. Turn to the left. Turn to the right. Turn to the right. Use magic marker. Dont use magic marker. Set marker color. Set marker thickness. Example command smidge.forward(100); smidge.back(37.8); smidge.forward(-37.8); smidge.turnLeft(30); smidge.turnRight(22.5); smidge.turnLeft(-22.5); smidge.setPenDown(true); smidge.setPenDown(false); smidge.setColor(Color.red); smidge.setThickness(5);
Like buckets, turtles use animation. The TurtlePanel class is almost exactly the same as the BucketPanel class; in fact, the only difference between the two is the names Turtle and Bucket. In addition to the instance methods shown above (that act on individual turtle objects), the turtle class has various static methods that affect the general turtle environment. Action Clear the screen. Get the current turtle image. Set the animation speed. Turn animation off. Example command Turtle.clear(Color.green); Turtle.getImage() //Used in TurtlePanel class. Turtle.setSpeed(10); Turtle.setCrawl(false);
In addition to the methods shown here, the Turtle class specifies an abstract method drawShape. Each of the classes you write that extend Turtle must define this method drawShape. Remember that we said turtles draw pretty shapes? All turtles must draw pretty shapes because the keyword abstract forces you to define the drawShape method. Consult the Turtle API at www.tjhsst.edu/compsci for the complete Turtle documentation.
Two-23
Unit2
Java
Lab06
Square Turtles
Objective To understand turtles and implement an abstract method. Background Three important points about the SquareTurtle class: 1. SquareTurtle extends Turtle. SquareTurtle is the sub-class. This creates a hierarchy where Turtle is the super-class and Turtle SquareTurtle 2. The Turtle class has two constructors, one that requires three arguments and a no-args constructor. Turtles no-args constructor puts a turtle at the origin facing north. SquareTurtles constructors use Turtles constructors with the keyword super. 3. Turtle is an abstract class, so SquareTurtle must provide a definition for Turtles abstract method drawShape. Overriding a method is when a sub-class provides a definition for a super-class method. The overridden method is the one that gets used by SquareTurtle objects. Turtle coordinates work just like panels and frames, only the turtle image is always 600x600. Depending on the size of your frame the turtle image will be scaled. The demos are all done with a 400x400 frame. Specification Filename Unit2\Lab06\SquareTurtle.java (load). Complete the SquareTurtle class by implementing the drawShape method. Note that this is required because drawShape is tagged abstract in Turtle. Filename Unit2\Lab06\Driver06.java (load). Create four turtles such that you use all four of the square turtles constructors. Draw squares of various colors, sizes, and thickness. Change one of your turtles sizes in the program so that one turtle ends up drawing two squares with different sizes. Test Data Go to www.tjhsst.edu/compsci.
Two-24
Java
Unit2
Exercises
Lab06
Note the three special-case triangles shown below. Use Math.sqrt(3.0) for the square root of three.
x
Complete the drawShape method for each of the three Turtle classes shown below.
x 2x
3x
x
2x
Two-25
Unit2
Java
Discussion
References
Imagine a method that requires an argument of type Turtle. public static void foo(Turtle arg) { arg.forward(12.345); arg.turnLeft(60); arg.drawShape(); //executes polymorphically } The method foo is valid because each of the turtle methods it calls are specified in the Turtle class. But what actually happens when foo executes? public static void main(String[] args) { SquareTurtle smidge = new SquareTurtle(); foo(smidge); } smidge arg
OBJECT
Recall that smidge is only a reference to our turtle object. When smidge is passed to the method foo, only the reference is copied. No new turtle object is created by passing a turtle as an argument to a method. Both the reference named smidge in main and the reference named arg in foo point to the same object. The actual object, of course, is of type SquareTurtle. Thus, arg is a reference of type Turtle that does not point to an object of type Turtle; it points to an object that is a sub-class of Turtle. In fact, because Turtle specifies the abstract method drawShape, the entire Turtle class must be tagged abstract. This means that you cannot create any instances of the Turtle class itself. So our Turtle type reference named arg must always point to an object of one of Turtles sub-classes. Turtle
SquareTurtle EquilateralTurtle
ThirtySixtyNinetyTurtle FortyFiveFortyFiveNinetyTurtle
Classes that can be instantiated are called concrete class. Turtle is not a concrete class. Turtle is an abstract class. The other four classes shown here are all concrete. You can create objects of these classes. The machine waits until runtime to decide which drawShape to execute. At that point, the actual type of
Two-26
Java
Unit2
the object that arg points to is known. This is called dynamic binding, or late binding.
Lab07
Polygon Turtles
Objective To solve a generic problem with turtles. Background Square turtles stored the size of their squares using an instance field named mySize. The default value for mySize was 50.0 (decimal values are truncated to integer coordinates on the actual turtle image). Polygon turtles store the size of their polygons similarly. They also store the number of sides for their polygon using another instance field named mySides. Note that mySize is a decimal value (double) and mySides is an integer (int). Look at PolygonTurtles five-argument constructor. Note that the first command explicitly invokes the superclass constructor (in this case the Turtle classs three-argument constructor). There is no call to super in either of the other two constructors. In those cases the machine will automatically call the superclasss no-args constructor. Alternatively, we could explicitly call super();. Specification Copy the TurtlePanel.class file from Unit2\Lab06 to Unit2\Lab07 noting that you do not need the source code so you do not have to copy the TurtlePanel.java file. Also copy the two class files for the inner class and the anonymous inner class. Both of these other files will begin with TurtlePanel and a dollar sign ($). Filename Unit2\Lab07\PolygonTurtle.java (load). Complete the implementation of the PolygonTurtle class. Do you remember the exterior angle theorem from geometry? Filename Unit2\Lab07\Driver07.java (load). Create different turtles such that you use all of PolygonTurtles constructors. Draw various types of polygons. Test Data Two-27
Unit2
Java
Go to www.tjhsst.edu/compsci.
Exercises
Lab07
The SquareTurtle class handled a specific case of the more generic PolygonTurtle functionality. The drawShape methods for two StarTurtle classes are shown below. The first StarTurtle draws a fivepointed star with each segment of length mySize. The second StarTurtle draws a generic star; the length of each segment is still mySize, but there are mySides many points to the star and the turtle makes myRotations many complete rotations in drawing the star. To clarify myRotations, note that a turtle makes two complete rotations in drawing the specific five-point star. 1) Five-Pointed StarTurtle public void drawShape() {
} 3) What are some advantages of the five-pointed StarTurtle over the generic StarTurtle?
4) What are some advantages of the generic StarTurtle over the five-pointed StarTurtle?
Two-28
Java
Unit2
Discussion
Access Modifiers
The two access modifiers we will use in this course are public and private. In short, public grants access to everyone and private grants access to no one. As a matter of convention all fields are private. public class FlowerTurtle extends Turtle { private double mySize; private Color myColor; . . . } The driver program, which acts as a client of the FlowerTurtle resource, cannot directly access the values of mySize and myColor. (The prefix my is also a convention, meant to convey the fact that each object knows its own size and its own color.) Rather than having direct access to these values, the user, in this case Driver08.java, must manipulate mySize and myColor with public methods. The constructors initialize these fields to default or specified values and two public methods called modifiers or mutators allow the user/client/driver to change the initial values. As a convention modifiers begin with the prefix set, and thus are often called setters. public class Driver08 //client program { public static void main(String[] args) { FlowerTurtle smidge = new FlowerTurtle(); FlowerTurtle lisa = new FlowerTurtle(300.0, 50.0, Color.red); smidge.setSize(25.0); lisa.setColor(Color.blue); } } Most methods we write will be tagged public so that you can use those methods in other classes. In FlowerTurtle, though, two helper methods will be tagged private. A FlowerTurtles drawShape method draws a pretty flower. This process is broken into two parts: drawing the petals and drawing the stem. To help organize the coding of these two processes drawShape is simply: public void drawShape() { drawPetals(); drawStem(); } The actual drawing of the flower is taken care of by the two private helper methods drawPetals and drawStem. Since Driver08.java is only interested in calling drawShape (to draw a complete flower), these two helper methods do not need to be publicly accessible. private void drawPetals() //only called from within the FlowerTurtle class { . . . }
Two-29
Unit2
Java
Lab08
Flower Turtles
Objective To tiptoe through the tulips. Background One other access issue has to do with overridden methods. Once a method has been overridden, the original method (the one that would have been inherited if it hadnt been overridden) cannot be invoked. For example: public class Driver08 { public static void main(String[] args) { FlowerTurtle smidge = new FlowerTurtle(); FlowerTurtle lisa = new FlowerTurtle(300.0, 50.0, Color.red); smidge.setSize(25.0); lisa.setColor(Color.blue); //calls FlowerTurtles setColor, not Turtles } Lisas setColor simply stores a color. Turtles setColor sets the color of a turtles magic marker. One lesson, then, it to be careful of the names you give to your methods. However, all is not lost. The superclass setColor can be called from within the definition of the class that overrode it. So from inside FlowerTurtle, Turtles setColor can be invoked. For example: private void drawPetals() { super.setColor(myColor); //calls Turtles setColor, changing the color of the pen . . . } This syntax is only valid from within FlowerTurtles definition. You cannot do this from Driver08. Specification Copy the three TurtlePanel class files into Unit2\Lab08. Filename Unit2\Lab08\FlowerTurtle.java (load). Complete the FlowerTurtle class by implementing the drawPetals and drawStem methods. There are thirty petals in the flowers shown here. The stems are one-and-a-half times as long as the petals, with leaves at forty-five degree angles. One leaf is only half the petal length. Filename Unit2\Lab08\Driver08.java (load). Turn the crawl off to speed up drawing and draw pretty flowers. Test Data Go to www.tjhsst.edu/compsci.
Two-30
Java
Unit2
Exercises
Lab08
Answer these questions about FlowerTurtle. 1) The third flower shown here is different from the other three. Which method in FlowerTurtle would have to change in order to draw this different type of flower?
2) In fact, this flower is produced by drawing squares in place of straight lines. Write out the implementation for the method that was your answer to Question #1 in order to draw this type of flower.
3) What would have to change about your FlowerTurtle class so that you could use any type of polygon and not just a square?
4) It turns out that it is easier in this case to simply rewrite the code from SquareTurtle and PolygonTurtle, rather than creating separate SquareTurtle and PolygonTurtle objects to draw these special flowers. Why?
Two-31
Unit2
Java
Lab09
Twisty Turtles
Objective To draw a pretty picture with a turtle. Background The twisty turtles are known for their marvelous pictures. Each picture is the result of following a relatively simple rule. Start with a segment of length five. So long as the length is less than some specified size (mySize is 400 as shown here to the right), draw a egment at the current length and turn left 123 degrees. Increment the segment length by ten for each repetition. The same procedure with a turn of twenty degrees and an increment of only two units produces the figure show here to the left. Repeat until the segment length is 125. Instead of drawing only one segment each time, draw an entire square based on the current segment length. Turn forty-five degrees each time and increment by five units. A max size of 150 is shown here to the right. Specification Copy the three TurtlePanel class files into Unit2\Lab09. Filename Unit2\Lab09\TwistyTurtle.java. You may use the SquareTurtle.java file as a model. Implement your favorite twisty turtle design. Filename Unit2\Lab09\Driver09.java. Draw your design. Test Data Go to www.tjhsst.edu/compsci. Extension Have your TwistyTurtle class implement the Runnable interface. Implement the method run. All run will do is set the turtles color and thickness, then call drawShape. In your driver, create multiple twisty turtle objects each with its own thread. Start the threads and watch your turtles twist in parallel.
Two-32
Java
Unit2
Discussion
Timers
The commands: Timer t = new Timer(1000, new Listener()); t.start(); create a timer object named t that ticks or fires every 1000 milliseconds. This means that once every second our timer will cause an event to occur. The result of that event will be determined by the listener, the second argument passed to the Timer constructor. Notice that this argument is an anonymous object of the class Listener. The Listener class is defined in the following format: private class Listener implements ActionListener { public void actionPerformed(ActionEvent e) { /************************/ /* */ /* Your code goes here. */ /* */ /************************/ } } The Listener class is being defined within another class. We tag the Listener class itself as private because its role is specialized and only relevant to the particular problem of this one single lab. Notice that Listener implements ActionListener. This means that we must define all the abstract methods specified in the ActionListener interface. ActionListener specifies only one such method, named actionPerformed, and it is often the only method defined for a listener class. Our timer fires by calling its listeners actionPerformed method. The timer knows that the anonymous object passed above must have such a method because actionPerformed was tagged abstract in the ActionListener interface. Once we specify the interval of time between each tick (always in milliseconds) and the listener object that should respond to each tick, that listeners actionPerformed will be called automatically on a regular interval. This is very similar to what happens whenever you press a button in a Graphical User Interface (GUI), which we will study in Unit3. Every time a button is pressed the button calls its listeners actionPerformed method. The result of pressing the button is determined by the definition of the listeners actionPerformed. A timer is just an invisible button that the machine automatically presses for us at a regular interval, thus causing some action to be repeatedly performed. Of course, you can have more than one timer each with its own different listener (or two timers may share the same listener if that is appropriate). Just create multiple timer objects each associated with an appropriate listener object. These anonymous listener objects can be created from different listener classes, but each listener class must follow the format specified above. For continuous repetition of an action, set the time interval between ticks to zero milliseconds. The timer then functions much like a loop. In addition to the start method shown above there is also a stop method. Clever manipulation of timers can lead to many interesting applications.
Two-33
Unit2
Java
Lab10
Polka Dots
Objective To understand timers. Background We will continue to use an off-screen buffer to draw our pictures. Earlier you may have noticed that we called our buffered-image either image or myImage. Convention dictates that the prefix my be used only for fields. Anytime our buffered image was a field it was called myImage and anytime it wasnt a field it was called image. But when should it be a field? To make this decision you must ask yourself another question. Where in my program do I need to access this object? If you only need the object in a single method then declare the object right there in that method and dont use the prefix my. This is called a local declaration. If you need the object in more than one method then you might want to declare it as a field with the prefix my. Another option is to pass the object as an argument, but this is not always possible when you are overriding methods or implementing abstract methods because you cannot change the argument list. Your decision must take into account the larger topic of scope. In the PolkaDotPanel class we represent the center of a circle, or polka dot, with the fields xPos and yPos. These variables are the current coordinates for the center of our circle. When the driver adds the panel to the frame and the frame is displayed to the screen, our overridden paintComponent method will be called automatically. This will display our buffered-image to the screen. Initially, though, our buffered-image will be a blank gray background. We set up a timer to fire once every second and define its listeners actionPerformed to do the following: 1. Pick random coordinates for a polka dot. 2. Draw the polka dot on the buffered-image at those random coordinates. 3. Force the panel to display the updated image by executing paintComponent again. This is achieved by calling the method repaint. Since we do not have direct access to the graphics part of the panel itself, we cannot directly call paintComponent (What would we pass for the Graphics g argument?). We can only call paintComponent indirectly by telling the panel to repaint. This process repeats once every second, each time the timer ticks. Specification Filename Unit2\Lab10\PolkaDotPanel.java (load). Edit the code so that only the current circle is shown to the screen. Filename Unit2\Lab10\Driver10.java. You can use the Driver00.java file as a model, only make sure to add a panel of type PolkaDotPanel. Test Data Go to www.tjhsst.edu/compsci.
Two-34
Java
Unit2
Lab11
Pinball
Objective To use timers and variables to simulate motion. Background The reason we use an off-screen buffer is to avoid seeing a flicker each time we clear the screen. The offscreen buffer doesnt really eliminate the flicker so much as it moves the flicker off the screen so that we dont see it. Each time the updated image is displayed all we perceive is the slight change in whats been drawn this time from what was drawn the previous time. Put enough of these slight changes together and it looks like motion.
The shell for this lab has the horizontal motion somewhat working and the vertical motion completely wrong. The basic idea for changing the (x, y) coordinates smoothly is to add some value to both xPos and yPos whenever the timer fires. We call this value dx or dy, for delta-x or delta-y, as in the change in x or the change in y. To make the pinball bounce, we change dx or dy from positive to negative or negative to positive, as appropriate. Then subsequent additions actually move (x, y) in the opposite direction. Specification Filename Unit2\Lab11\PinballPanel.java (load). Edit the code so that the pinball bounces off each side of the panel correctly. Filename Unit2\Lab11\Driver11.java. Create an appropriate driver. Test Data Go to www.tjhsst.edu/compsci.
Two-35
Unit2
Java
Lab12
Get the Prize
Objective To synthesize previous concepts. Background The pinball in this problem is just like the pinball from Lab11. The prize in this problem is just like the randomly placed polka dot from Lab10 (only smaller and red). Since you now have two circles to keep track of, change RADIUS to R1 and R2, and change xPos and yPos to x1, y1, x2, and y2. If you know the distance formula then you can determine when your pinball hits the prize. Find the distance between the two centers using Math.sqrt and Math.pow. To square an expression use: Math.pow(x2 x1, 2) The second argument indicates the power that the first argument should be raised to. In this case we are squaring the expression x2 x1 so the second argument is two. Its best not to check equality when dealing with decimal values. If the distance between the two centers is less than or equal to the sum of the radii then youve hit the prize. Specification Filename Unit2\Lab12\PrizePanel.java. Each time your pinball hits the prize, move the prize to some other location. Keep a running total of the number of hits and display this total on the screen. Filename Unit2\Lab12\Driver12.java. Create an appropriate driver. Test Data Go to www.tjhsst.edu/compsci.
Two-36
Java
Unit2
Project
Riddle Me This
Objective To make your teacher and classmates laugh. Background The graphics object created for an image is not directly of type Graphics. The object is actually an instance of a subclass of Graphics. To cast an object to a subclass type use: private Graphics2D myBuffer; ... myBuffer = (Graphics2D)myImage.getGraphics(); This is required if you want to use a method defined for the subclass Graphics2D that is not also defined in Graphics. If the method was overridden rather than added then you would not have to cast. A reference of type Graphics cannot call methods it doesnt know even if the actual object does know those methods. To change the thickness of the outline for drawing shapes use the commands: myBuffer.setStroke(new BasicStroke(10.0f)); //10 pixels wide This does not work without casting because the Graphics class does not specify a method setStroke. Specification Filename Unit2\Project\ProjectPanel.java. Use at least one image, various shapes, at least two different pen-widths, and text output. Ask, answer, and illustrate a humorous riddle. Use multiple timers for animation and to reveal the answer to the riddle. Filename Unit2\Project\ProjectDriver.java. Create an appropriate driver. Test Data Go to www.tjhsst.edu/compsci.
Two-37
Unit2
Java
Lab14
Hit the Bumper
Objective To solve a hard problem. Background This problem is just like Lab12 but with a bumper in the middle of the screen. Your pinball should bounce off the sides of the bumper in the same way it bounces off the sides of the panel. It should bounce off the corners of the bumper just like a real pinball would bounce off the corners of a real bumper. You may find it helpful to define a method for finding the distance between two points. public double distance(double x1, double y1, double x2, double y2) { return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)); } You may also find it helpful to define a method for determining whether or not a particular point is inside your bumper. Make sure you dont put the prize behind the bumper. These methods will make it easier to solve this problem because your code will be shorter and more readable. It is often helpful to define methods for any process used repeatedly. Helpful methods like these are called helper methods. Specification Filename Unit2\Lab14\BumperPanel.java. You can use the PrizePanel.java file as a model. Add a bumper as described above. Filename Unit2\Lab14\Driver14.java. Create an appropriate driver. Test Data Go to www.tjhsst.edu/compsci.
Two-38
Java
Unit2
Lab15
Karel the Robot
Objective To solve a really hard problem. Background Cycling through a series of images stored in an array can create the appearance of motion if the images are chosen carefully. The one image that actually gets displayed at any one moment is determined by the value of some variable that cycles from 0 to 1 to 2 to 3 to 0 to 1 and so on. Each image is just a still shot but the cycling of images gives the appearance of motion. Your solution to this problem will use the karel the robot images instead of the duke images shown here. As you cycle from one image to another it will appear as though the robot is turning. To get the width or height of a particular image use the commands: int width = array[0].getImage().getWidth(null); int height = array[0].getImage().getHeight(null); Again null refers to a required argument of type ImageObserver. Since we are not interested in observing this image we do not pass an object to the method. However, we must explicitly state that we are not passing an object by passing null, the Java keyword indicating the absence of an object. Specification Filename Unit2\Lab15\KarelPanel.java. You can use any of the animation panels as a model. If you can reverse engineer the demo and successfully replicate karel the robot type motion, please e-mail mr@torbert.com or otherwise contact Mr. Torbert. He will be impressed. Filename Unit2\Lab15\Driver15.java. Create an appropriate driver. Test Data Go to www.tjhsst.edu/compsci. array
Two-39