Parameters
Handling Redundancy
Consider the task of printing the following lines and boxes:
*************
*******
***********************************
**********
* *
**********
*****
* *
* *
*****
Here is (most of) a first solution:
public class Stars {
public static void main(String[] args) {
write13Stars();
write7Stars();
write35Stars();
draw10x3Box();
draw5x4Box();
}
public static void write13Stars() {
for (int i = 1; i <= 13; i++) {
System.out.print("*");
}
System.out.println();
}
public static void write7Stars() {
for (int i = 1; i <= 7; i++) {
System.out.print("*");
}
System.out.println();
}
public static void write35Stars() {
for (int i = 1; i <= 35; i++) {
System.out.print("*");
}
System.out.println();
}
// and so on and so on
}
This code is redundant. Would variables help?
Would constants help?
What would be a better solution?
- A method to print a line with any number of stars.
- A method to print a box of any size.
Parameterization
A
parameter is a value passed to a method by its caller.
Instead of three methods:
write13Stars,
write7Stars,
and
write35Stars, we would like one
method
writeStars and
pass the length of the line to
the method:
writeStars(13),
writeStars(7),
and
writeStars(35).
When declaring the method, we need to state that it requires a parameter
for the number of stars. When calling the method, we need to specify how
many stars to print.
Declaring a Parameter
To declare a parameter, you specify its type and its name within
the parentheses, for example:
public static void writeStars(int number) {
// need code here to print some stars
}
In general, the syntax for defining a method with a parameter is:
public static void methodName(type parameterName) {
statement(s)
}
The name of the parameter is also called the
formal parameter.
Passing a Parameter
When
writeStars is called, the caller must specify
the parameter value, for example:
public static void main(String[ ] args) {
writeStars(10);
int x = 13;
writeStars(42 - x);
}
Once we have finished the
writeStars method, the output will
be:
**********
*****************************
In general, the syntax for passing a parameter is:
methodName(expression);
The expression that is passed is called the
actual parameter.
Parameters and Loops
A parameter can guide the number of repetitions of a loop.
In the
writeStars method, the parameter indicates the
number of repetitions we want.
public static void writeStars(int number) {
for (int i = 1; i <= number; i++) {
System.out.print("*");
}
System.out.println( );
}
Activity: Change the Stars program to use the
writeStars method.
writeBlanks
How Parameters Are Passed
When the method is called:
- The value is stored in the parameter variable.
- The method's code is executed.
- When the method ends, the parameter variable is "erased".
writeStars(3) -----> initialize number to 3
execute writeSpaces method
when the method ends, number is erased
writeStars(7) -----> initialize number to 7
execute writeSpace method
when the method ends, number is erased
Activity: Determine what happens for the following method
calls:
writeStars(2);
writeStars(0);
writeStars(-1);
Activity: What does the following program output and why:
public class ParameterTest {
public static void main(String[] args) {
int x = 3;
System.out.println("x is " + x);
increment(x);
System.out.println("x is now " + x);
}
public static void increment(int x) {
System.out.println("In increment x is " + x);
x = x + 1;
System.out.println("In increment x is now " + x);
}
}
increment activity
Today's News: October 1
Quiz 4 is available, due on Saturday
Common errors
- If a method has a parameter, it is illegal to call it
without passing any value for that parameter.
writeStars( ); // ERROR: parameter value required
- The value passed to a method must be of the correct type.
writeStars(3.14); // ERROR: must be of type int
- Don't use the type in the method call.
int x = 5;
writeStars(int x); // ERROR: type of x already declared
Multiple Parameters
A method can accept multiple parameters, which are separated by
commas. When calling it, you must pass a value for each
parameter, for example:
public static void main(String[] args) {
multiply(3, 4);
multiply(5, 2);
}
public static void multiply(int number1, int number2) {
int product = number1 * number2;
System.out.print(number1);
System.out.print(" times ");
System.out.print(number2);
System.out.print(" equals ");
System.out.println(product);
}
Output:
3 times 4 equals 12
5 times 2 equals 10
The syntax for defining a method with multiple parameters is:
public static
void methodName(type parameterName, ..., type parameterName) {
statement(s);
}
The syntax for passing multiple parameters is:
methodName(expression, ..., expression);
Activity: Add a parameterized method to print a line with a
given length and a given character.
Activity: Add a parameterized method to print boxes in the
Stars program.
Activity Solution
We want to print a box with a specified height and width, so the
height and width will be parameters. Both parameters will be
integers. The parameters can be coded as follows:
public static void drawBox(int height, int width) {
// print a box with a specified height and width
}
The height is the number of lines. The first and last lines will
be stars, while the other lines (height – 2 of them) will consist of a
star, some spaces, and another star.
The width is the number of characters to print on each line. All
the characters on first and last lines will be stars. The other
lines will only have two stars, which means that the number of spaces
will be width – 2.
Based on this analysis, here is the pseudocode to print a box with a
specified width and height:
- Print a line with width stars.
- Do the following height – 2 times.
Print a line with a star, width – 2 spaces, and a star.
- Print a line with width stars.
Note that we already have a method to print a line of stars. We
can use it to print the first and last lines.
With this in mind, the pseudocode can be implemented as follows.
public static void drawBox(int height, int width) {
// print a box with a specified height and width
// 1. Print a line with width stars.
writeStars(width);
// 2. Do the following height - 2 times.
for (int i = 0; i < height - 2; i++) {
// A. Print a line with a star, width - 2 spaces, and a star.
System.out.print("*");
for (int j = 0; i < width - 2; j++) {
System.out.print(" ");
}
System.out.println("*");
}
// 3. Print a line with width stars.
writeStars(width);
}
Here is an outline of the full Stars program.
How can you print the extra newline between lines and boxes?
Activity: Modify the Stars program to input the length of a
line and the size of a box from the keyboard.
public class Stars2 {
public static void main(String[] args) {
writeStars(13);
writeStars(7);
writeStars(35);
drawBox(10, 3);
drawBox(5, 4);
}
// Put writeStars method here
// Put drawBox method here
}
Methods That Return Values
Parameters send information in from the caller to the method.
Return values send information out from a method to its caller.
We will look at the Math class, and how to write methods that return
values.
The Math Class
The Math class defines the constants
Math.E (2.7182818...)
and
Math.PI (3.1415926...) and provides many useful
operations for mathematical calculation.
Here are some of them.
Method | Description |
double Math.abs(double value) | absolute value |
int Math.abs(int value) | absolute value |
long Math.round(double value) | nearest whole number |
double Math.ceil(double value) | rounds up |
double Math.floor(double value) | rounds down |
double Math.log(double value) | logarithm, base e |
double Math.log10(double value) | logarithm, base 10 |
double Math.max(double value1, double value2) | larger of two values |
int Math.max(int value1, int value2) | larger of two values |
double Math.min(double value1, double value2) | smaller of two values |
int Math.min(int value1, int value2) | smaller of two values |
double Math.pow(double base, double exp) | base to the exp power |
double Math.sqrt(double value) | square root |
double Math.random() | random double between 0 and 1 |
Calling Math Methods
- The Math methods do not print to the console.
- Each method produces ("returns") a numeric result.
- The results are used as expressions (printed, stored, etc.).
Here are some examples:
double result = Math.sqrt(9.0);
System.out.println(result);
result = Math.abs(-3.33);
System.out.println(result);
result = Math.round(1.75);
System.out.println(result);
result = Math.pow(3.0,4.0);
System.out.println(result);
Output:
The syntax for calling a Math method is:
Math.methodName(parameters)
Activity:
Evaluate the following expressions:
- Math.abs(-1.23)
- Math.pow(3, 2)
- Math.pow(10, -2)
- Math.sqrt(121.0) - Math.sqrt(256.0)
- Math.round(Math.PI) + Math.round(Math.E)
- Math.ceil(6.022) + Math.floor(15.9994)
- Math.abs(Math.min(-3, -5))
Math.max and
Math.min can be used to bound numbers.
Consider an
int variable named
age.
- What expression would change negative ages to 0?
- What expression would cap the maximum age at 40?
Math Activity
Writing Methods That Return Values
To write methods that return values, you need to declare the method's
return type and you need a
return
statement. Here is a method that converts temperatures
in Fahrenheit to Celsius.
public static double fahrenheitToCelsius(double degreesF) {
double degreesC = 5.0 / 9.0 * (degreesF - 32);
return degreesC;
}
The
double in the header is the return type. The
statement
return degreesC; is the return statement.
The syntax for a method that returns values is:
public static returnType methodName(formalParametersList) {
statement(s);
return expression;
}
Here is an example of a main method that uses the
fahrenheitToCelsius method.
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
System.out.print("Enter the temperature in Fahrenheit");
double tempF = console.nextDouble( );
double tempC = fahrenheitToCelsius(tempF);
System.out.println("That is " + tempC + " degrees in Celsius");
}
The
fahrenheitToCelsius method is called with the value of
tempF. The return value is stored in the variable
tempC. Because of scope, the variable
degreesC
in
fahrenheitToCelsius cannot be accessed by the main
method. Also, because of scope, the variable
tempF in
the main method cannot be accessed
by
fahrenheitToCelsius. Parameters and return values
are how information is passed back and forth.
The syntax for calling a method and storing the return
value in a variable is:
returnType variable
= methodName(actualParameters);
A method that returns a value can have multiple parameters and can
call methods as well. For example, here is a method
that returns the maximum of three numbers.
public static double max3(double a, double b, double c) {
double max = Math.max(a, b);
// max contains the maximum of a and b
max = Math.max(max, c);
// max contains the maximum of its old value or c
return max;
}
Activity: Write a method that converts Celsius to Fahrenheit.
Activity: Write a method that returns the circumference of
a circle from its radius.
Activity: Write a method that returns the area of a
rectangle from its length and width.
Activity Methods with Return Values
Activity Solution
The general structure of a method that has parameters and returns
a value is:
public static ?returnType? ?methodName?(?parameters?) {
// need to calculate value to be returned
return ?result?;
}
Question marks and comments show information that we need to fill in.
Let's name the method
rectangleArea.
public static ?returnType? rectangleArea(?parameters?) {
// need to calculate value to be returned
return ?result?;
}
We need to know the length and width to compute the area so they must
be parameters.
public static ?returnType? rectangleArea(?type? length, ?type? width) {
// need to calculate value to be returned
return ?result?;
}
There is no reason why length and width have to be integers. For
example, the width of the textbook is about 7.4 inches. The best
data type for both parameters is
double.
public static ?returnType? rectangleArea(double length, double width) {
// need to calculate value to be returned
return ?result?;
}
The return type will depend on the type of the result that is
calculated in the method, so let's postpone that decision.
The area can be calculated by multiplying the length times the
width. We can add this expression in the method and store the
value in a variable.
public static ?returnType? rectangleArea(double length, double width) {
// need to calculate value to be returned
?type? ?variable? = length * width;
return ?result?;
}
Let's name the variable
area. Multiplying two real
numbers results in another real number, so the type should be
double.
public static ?returnType? rectangleArea(double length, double width) {
// need to calculate value to be returned
double area = length * width;
return ?result?;
}
area contains the result that we want to return. Because
area is a
double, that means the return type of the
method should also be a
double.
public static double rectangleArea(double length, double width) {
// need to calculate value to be returned
double area = length * width;
return area;
}
Challenge: Write a method that returns the base 2 logarithm of a
number.
Challenge: Write a method that returns the fractional part of a
double.
Today's News: October 3
Quiz 4 is available, due on Saturday
Objects and Classes
An
object is an entity that contains
data (variables) and behavior (methods).
A
class is a type of object,
for example:
- The Scanner class represents objects that read information
from the keyboard, files, and other sources.
- The String class represents objects that store text.
- The DrawingPanel
class represents graphical window objects.
- The Graphics, Color, and Font classes
represent some of the components of graphical window objects.
In general, to program with classes, you need to understand how
to
construct an object (that is, create and initialize an
object) and how to
call methods on the object (that is, perform
operations on the object's data).
The String Class
The
String class is a special class because you don't have to use
the
new keyword to construct a
String object, and because
Java includes a
+ operator for
String. Other than that,
you call methods on
Strings just like other objects.
For example, the
length method returns the length of the
string.
String greeting = "Hello";
int len = greeting.length( );
System.out.println("The length of " + greeting + " is " + len);
Note how the method call
greeting.length( ) follows the
pattern
variable.method( ). Because
the
length method returns a value, in particular
an
int, we can store the value of the method call in
an
int variable. The above code fragment produces the
output:
The
charAt method returns the character at a specified
index. An
index is an integer used to specify the
location in a sequence.
String greeting = "Hello";
char c = greeting.charAt(1);
System.out.println("The character at index 1 of " + greeting + " is " + c);
Note how the method call
greeting.charAt(1) follows the
pattern
variable.method(parameter).
This is because
charAt requires one parameter.
Because the
charAt method returns a
char value,
we can store the value of the method call in
a
char variable. The above code fragment produces the
(perhaps puzzling) output:
The character at index 1 of Hello is e
You might think that the character at index 1 should be
'H',
but Java (as well as many other programming languages)
uses
zero-based indexing. As a result, although
the string
"Hello" has a length of 5, its indexes go from 0 to 4.
Index |
0 | 1 | 2 | 3 | 4 |
Character |
H | e | l | l | o |
Here are some useful methods for operating on
Strings.
Method |
Return Type |
Description |
charAt(int index) |
char |
returns the character at the index |
compareTo(String text) |
int |
returns a negative number if the string is before the text
alphabetically, a positive number if the string is after the text
alphabetically,or zero if the string is equal to the text |
endsWith(String text) |
boolean |
returns true if the string ends with the text |
equals(String text) |
boolean |
returns true if the string is equal to the text |
indexOf(String text) |
int |
returns the index of the text or –1 |
length( ) |
int |
returns the length of the string |
startsWith(String text) |
boolean |
returns true if the string starts with the text |
substring(int start, int end) |
String |
returns the string from the start index to before the end index |
substring(int start) |
String |
returns the string from the start index to the end of the string |
toLowerCase( ) |
String |
returns a new string with all letters in lowercase |
toUpperCase( ) |
String |
returns a new string with all letters in uppercase |
trim( ) |
String |
returns a new string with the leading and trailing white space removed |
The
StringTest program calls some of these methods.
public class StringTest {
public static void main(String[] args) {
String string1 = "Four score and seven years ago";
trySomeStringMethods(string1);
String string2 = "To be or not to be";
trySomeStringMethods(string2);
}
public void trySomeStringMethods(String line) {
System.out.println("The line is: " + line);
char c = line.charAt(3);
System.out.println("The char at index 3 is " + c);
int index = line.indexOf("or");
System.out.println("or is at index " + index);
boolean start = line.startsWith("Four");
System.out.println("It is " + start + " that the line starts with Four");
String upper = line.toUpperCase( );
System.out.println("The line in upper case is " + upper);
}
}
Activity: Change the StringTest program to read two
lines from the keyboard and to call all the String methods listed
above.
What happens if you enter a line with less than 4 characters?
It is often useful to process each character in a
String. Using the
charAt and
length
methods and a for loop, this is easy to do.
String string1 = "Four score and seven years ago";
for (int i = 0; i < string1.length( ); i++) {
char c = string1.charAt(i);
System.out.println("Process char " + c + " here");
}
Activity: Write a program that inputs a line and prints
the result of calling the indexOf method for each character.
Activity: Write a program that inputs a line and prints the
line with the characters in reverse order.
Simple String Expressions
Today's News: October 6
Lab 3 due Tuesday
The Scanner Class
You have already used the
Scanner class. Here is a code
fragment similar to what we programmed earlier with a more detailed
explanation.
// Set up a variable named console to read from the keyboard.
Scanner console = new Scanner(System.in);
// Prompt the user to enter information.
System.out.println("Enter height: ");
// Read value from keyboard, and store the value in a variable.
double height = console.nextDouble();
// Do another combination of prompt, read, and store.
System.out.println("Enter weight: ");
double weight = console.nextDouble();
- The first statement does the following:
- Scanner console declares a variable named
console, which can store Scanner objects.
-
new Scanner(System.in) constructs a Scanner object
with a parameter to enable input from the keyboard. Each class
has its own requirements for parameters to construct an object.
- The Scanner object is stored in console.
- The second statement prompts the user to enter information.
- The third statement does the following:
- double height declares a variable
named height, which can store doubles.
- console.nextDouble() calls the nextDouble
method of console. Think of it as asking
console to perform an action. In this case, the method
waits for the user to enter a value, and that value is
returned by the method.
- The value returned by the nextDouble method is stored in
height.
- The last two statements obtain another value from the
user. In particular, console
and nextDouble are used again. In general, a single object
can be used multiple times.
The
Scanner class includes the following constructors and
methods:
Constructor | Description |
new Scanner(System.in) | for keyboard input |
new Scanner(text) |
for reading one word at a time from a String (see Chapter 6, not covered in this course) |
new Scanner(file) | for input from a File
(see Chapter 6, not covered in this course) |
Method name | Description |
next( ) | reads and returns the next token as
a String |
nextDouble( ) | reads and returns a double |
nextInt( ) | reads and returns an int |
nextLine( ) | read and returns the next line
of input as a String |
The
next,
nextDouble, and
nextInt methods
all read one
token at a time, that is, a single word or
number. By default, the
Scanner class uses
whitespace to separate tokens. Whitespace includes
spaces, tab characters, and newline characters. Any punctuation
characters will be included in tokens.
The following
ThreeTokens program will read and print three
tokens from the keyboard no matter how many spaces and newlines
separate the tokens. Any extra tokens on the last line of input
will be ignored. Recall that you need the import statement
because the
Scanner class is part of the
java.util
package (Java does not include this package until you tell it to do
so).
import java.util.*;
public class ThreeTokens {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
System.out.print("Enter three tokens: ");
String token1 = console.next( );
String token2 = console.next( );
String token3 = console.next( );
System.out.println("The three tokens are:");
System.out.println(token1);
System.out.println(token2);
System.out.println(token3);
}
}
Activity: Change the ThreeTokens program to read three
ints or three doubles. What happens if you
enter something that is not a number?
Challenge: Create programs that intermix calls to the
nextLine method with the other methods for
Scanner. Try to precisely state how the
nextLine method behaves.
We will see many more examples of the syntax of constructing objects.
className objectVariable = new className(parameters);
the syntax of calling methods,
objectVariable.methodName(parameters)
and using methods like
next and
nextDouble that
return values.
Graphical Objects
Setting up the DrawingPanel
You must put the file
DrawingPanel.java
in each directory that will contain programs that use it.
- Start by putting it into your V:\drjava\lectures folder by right-clicking on the
above link and storing it there.
- Next download
DrawingPanelTest
and put it in the same directory.
- Start DrJava.
- Open DrawingPanel.java
- Open DrawingPanelTest.java
- Compile and run.
Drawing Panel Setup
Overview
We will draw graphics in Java using 3 kinds of objects:
- DrawingPanel: A window on the screen.
This is not part of Java, but is provided by the authors of the textbook.
- Graphics: A "pen" to draw shapes/lines on a window.
- Color: Colors in which to draw shapes.
DrawingPanel
The
DrawingPanel class allows you to create a window and to
access a
Graphics object to draw on the window. To use
the
DrawingPanel class, you need to include
DrawingPanel.java in the
same folder as your program. Here is an example to create a
window with a certain size.
DrawingPanel panel = new DrawingPanel(300, 200);
- The window has a width of 300 pixels and a height of 200
pixels. A pixel is a single small dot on a computer screen.
- The window has nothing on it.
- We can draw shapes and lines on it using a Graphics object.
Here are some useful methods for
DrawingPanel objects.
Method Name |
Description |
getGraphics( ) |
returns a Graphics object that the program can draw on |
setBackground(color) |
sets the background color |
sleep(milliseconds) |
pause for a given number of milliseconds (1000 milliseconds equals one second) |
All of these methods will eventually be discussed in more detail below.
Graphics
A
Graphics object is like a pen that allows you to draw lines
and shapes.
Access it by including this import statement on the top of your
program:
and calling
getGraphics on your
DrawingPanel object.
Graphics g = panel.getGraphics( );
You can draw and fill shapes by calling methods on your
Graphics
object.
g.drawRect(160, 30, 90, 65);
g.fillOval(80, 130, 90, 70);
Here is a complete program that contains this.
You can cut and paste it into Dr. Java to try it out.
Make sure you have already put
DrawingPanel.java in the same directory.
import java.awt.*;
public class SimpleDrawingProgram {
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(300, 200);
Graphics g = panel.getGraphics();
g.drawRect(160, 30, 90, 65);
g.fillOval(80, 130, 90, 70);
}
}
Result:
Coordinate System
A position on a window is specified by a pair of
coordinates,
usually integers and usually designated as (x,y).
- Each (x,y) position is a pixel ("picture element").
- (0,0) is at the window's top-left corner.
- x increases rightward and y increases downward.
For example, in the above picture, the top-left corner of the
rectangle is at the coordinates (160,30), which means 160 pixels to
the right and 30 pixels down. To understand
the coordinates for the oval, you need to imagine a rectangle that
encloses the oval. This is called a
bounding box.
The top-left corner of the oval's bounding box is at the coordinates
(80,140), which means 80 pixels to the right and 140 pixels down.
Graphics Methods
Here are some useful methods for operating on
Graphics objects.
Method |
Description |
drawLine(int x1, int y1, int x2, int y2) |
draws a line between (x1,y1) and (x2,y2) |
drawOval(int x, int y, int width, int height) |
draws an oval that fits within the specified rectangle |
drawRect(int x, int y, int width, int height) |
draws a rectangle with upper-left corner at (x,y) |
drawString(String text, int x, int y) |
prints the text string with lower-left corner at (x,y) |
fillOval(int x, int y, int width, int height) |
fills an oval that fits within the specified rectangle |
fillRect(int x, int y, int width, int height) |
fills a rectangle with upper-left corner at (x,y) |
setColor(Color color) |
changes the color to be used for drawing and filling |
Activity: Write a program that uses all the draw and fill
methods in the above list.
Today's News: October 8
Quiz 5 is available, due Saturday
Color
A color can be created one using Red-Green-Blue (RGB) values from 0 to
255, for example:
Color brown = new Color(192, 128, 64);
Or you can use a predefined Color class constant.
Color.BLACK Color.GRAY Color.ORANGE Color.YELLOW
Color.BLUE Color.GREEN Color.PINK
Color.CYAN Color.LIGHT_GRAY Color.RED
Color.DARK_GRAY Color.MAGENTA Color.WHITE
You can pass a color to
DrawingPanel's
setBackground method.
The overall window background color will change.
Color brown = new Color(192, 128, 64);
panel.setBackground(brown);
You can also set the color using
Graphics'
setColor method.
This color will be used in subsequent
Graphics operations.
The color of anything that was previously drawn will not change.
g.setColor(Color.BLACK);
g.fillRect(10, 30, 100, 50); // a black rectangle
g.setColor(Color.MAGENTA);
g.drawLine(300, 0, 0, 200); // a magenta line
g.setColor(Color.RED);
g.fillOval(60, 40, 40, 70); // a red oval
Result of
setBackground and
setColor examples:
One way to draw a colored shape with an outline is to first fill it,
then draw the same shape in the outline color.
import java.awt.*;
public class OutlineExample1 {
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(300, 200);
Graphics g = panel.getGraphics();
// inner red fill
g.setColor(Color.RED);
g.fillRect(120, 10, 100, 150);
// black outline
g.setColor(Color.BLACK);
g.drawRect(120, 10, 100, 150);
}
}
Another way to draw a colored shape with an outline is to first
fill the shape with the outline color, then fill a slightly smaller
shape with the inside color.
import java.awt.*;
public class OutlineExample2 {
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(300, 200);
Graphics g = panel.getGraphics();
// black outline
g.setColor(Color.BLACK);
g.fillRect(120, 10, 100, 150);
// inner red fill
g.setColor(Color.RED);
g.fillRect(121, 11, 98, 148);
}
}
Result of both outline examples:
Activity: Write a program that uses the setBackground
method and all the draw and fill methods with different colors.
Drawing with Loops and Methods
The parameters of a
Graphics method can use the loop counter
variable.
It is usually easier to start at 0.
This code draws 10 circles along a diagonal from lower right
to upper left.
DrawingPanel panel = new DrawingPanel(300, 300);
Graphics g = panel.getGraphics();
g.setColor(Color.RED);
for (int i = 0; i < 10; i++) {
g.fillOval(0 + 30 * i, 270 - 30 * i, 30, 30);
}
Suppose we want a method to draw these 10 circles.
We must pass the Graphics object as a parameter.
public static void drawCircles(Graphics g) {
g.setColor(Color.RED);
for (int i = 0; i < 10; i++) {
g.fillOval(0 + 30 * i, 270 - 30 * i, 30, 30);
}
}
Activity: Write a program that produces the following
picture.
Challenge: Write a program that produces the following
picture.
Hint: Use the
drawArc method of
the
Graphics class.
You can find another hint
here.
Progress 2
Work on these two graphics problems.
Today's News: October 10
Quiz 5 is available, due Saturday
Lab 4 is due on Tuesday of next week.
DrawingPanel's
sleep method pauses your program for
a given number of milliseconds. (There are 1000 milliseconds in
a second.) You can use sleep to create simple animations.
Activity: Rewrite the drawCircles method so that the
circle appears to move from the lower left to the upper right.
Activity Solution
To call the
sleep method, we need to pass the
DrawingPanel object to the
drawCircles method.
Here is a first version that adds a 500 ms sleep in the loop.
import java.awt.*;
public class MovingCircle {
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(300, 300);
Graphics g = panel.getGraphics( );
drawCircles(panel, g);
}
public static void drawCircles(DrawingPanel panel, Graphics g) {
g.setColor(Color.RED);
for (int i = 0; i < 10; i++) {
panel.sleep(500);
g.fillOval(0 + 30 * i, 270 - 30 * i, 30, 30);
}
}
}
There are two problems with this animation. The first is that
the previous circle needs to be erased before the next circle is
drawn. The second is that the circle needs to be drawn more
often for the animation to be smooth.
To address the second problem, one solution is to draw the circle more
often, perhaps every 3 pixels instead of every 30 pixels (using
3
* i instead of
30 * i). To get the last circle at
position (270,0), the loop variable
i needs to go up to
90. To have same rate of speed, the amount of sleep needs to be
changed to 50 ms. Make and test these changes in
the
MovingCircle program. You should see a solid red
diagonal line being drawn.
To address the first problem, we need to consider how to erase the
previous circle and when. Assuming the background color is
white, drawing a white circle with the same parameter values that were used
to draw the red circle should "erase" the red circle. If the
next red circle is drawn immediately after erasing the previous one,
then a blank window is unlikely to appear during the animation.
Note though that we will need to switch colors in the loop between
white and red. With all these considerations, our pseudocode
in the loop is:
- Sleep for 50 ms.
- Change the color to white.
- Fill the previous circle.
- Change the color to red.
- Fill the next circle.
This leads to the following program. Note that we get the
previous circle by using
i - 1
import java.awt.*;
public class MovingCircle {
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(300, 300);
Graphics g = panel.getGraphics( );
drawCircles(panel, g);
}
public static void drawCircles(DrawingPanel panel, Graphics g) {
for (int i = 0; i <= 90; i++) {
panel.sleep(50);
g.setColor(Color.WHITE);
g.fillOval(0 + 3 * (i - 1), 270 - 3 * (i - 1), 30, 30);
g.setColor(Color.RED);
g.fillOval(0 + 3 * i, 270 - 3 * i, 30, 30);
}
}
}
Here is another way of doing the same thing.
Instead of using a formula for x and y positions in terms of the loop parameter,
we just change the positions in the body of the loop.
We also change the angle at which the circle moves.
import java.awt.*;
public class BouncingBall1 {
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(300, 300);
Graphics g = panel.getGraphics( );
drawCircles(panel, g);
}
public static void drawCircles(DrawingPanel panel, Graphics g) {
int x = 0;
int y = 270;
int deltaX = 1;
int deltaY = -3;
for (int i = 0; i <= 90; i++) {
panel.sleep(50);
g.setColor(Color.WHITE);
g.fillOval(x, y, 30, 30);
g.setColor(Color.RED);
x = x + deltaX;
y = y + deltaY;
g.fillOval(x, y, 30, 30);
}
}
}
Activity: Bouncing Ball:
Part 1:
Copy the
BouncingBall1 program into Dr. Java and run it.
Change the name of the class to
BouncingBall2
and save it with the name
BouncingBall2 (using File -→ Save As).
Now duplicate the loop so that it runs twice. What does it do?
Now, between the two loops, insert the line:
deltaY = -deltaY;
And run it again. What happens?
Part 2:
Go back to
BouncingBall1, change the name of the class to
BouncingBall3, and save it.
Now change the loop so that the maximum value of
i is 180 instead of 90.
Run the program and think about what it does.
Now insert the following 2 lines at the end of the
for loop (before the closing brace):
if (i == 90)
deltaY = -deltaY;
Run the program and explain what you think the above two lines do.
Part 3:
Replace the test (i == 90) with a test to see of the circle is above the top of the window.
The test should not refer to the variable i.
Hint: The top of the circle is at y.
Why is this a better way to do the test?
Part 4:
Increase the limit on i from 180 to 360.
Add another test that changes deltaY again if the circle is below the bottom of the window.
Hint: The height of the window is 300 and the diameter of the ball is 30.
Part 5:
Add additional tests to bounce the ball off the sides of the window.
Part 6:
Notice that the diameter of the circle (30) and with width and height of the window (300 and 300)
are used in several places in the code.
Rewrite the code so that the size of the circle and the size of the panel can easily be changed in one place.
This is an example of refactoring.
Activity Bouncing Ball Progress
From
Wikipedia:
"Code refactoring is the process of restructuring exiting computer code ... without changing its external behavior. ...
Advantages include improved code readability and reduced complexity to improve source code maintainability ..."