previous
 next 
CS 1063  Weeks 6 and 7:  Parameters and Objects 
Fall 2014: Sections 1 and 2

Today's News: September 29
This is the start of Week 6

Objectives

Assignments

Contents



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?

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:
  1. The value is stored in the parameter variable.
  2. The method's code is executed.
  3. 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

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:
  1. Print a line with width stars.
  2. Do the following height – 2 times.
    Print a line with a star, width – 2 spaces, and a star.
  3. 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


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:
3.0
3.33
2.0
81.0

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 length of Hello is 5

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:
import java.awt.*;

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:
A rectangle and an oval

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:
A black rectangle, a magenta line, and a
			   red oval on a brown background

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:
A red rectangle with a black border
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.
10 circles, same center, different radiuses

Challenge: Write a program that produces the following picture.
Hint: Use the drawArc method of the Graphics class.
You can find another hint here.
A spiral

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:
  1. Sleep for 50 ms.
  2. Change the color to white.
  3. Fill the previous circle.
  4. Change the color to red.
  5. 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 ..."


 next notes
 next notes