Solution files: SmileyMain.java, UpgradedSmiley.java
Step 1 asked you to set the variable smiley
to be a new instance
of UpgradedSmiley
. This can be done with a single line of code inside
of the initializeSmiley
method:
smiley = new UpgradedSmiley();
Note that if you instead write this line:
UpgradedSmiley smiley = new UpgradedSmiley(); // this is not what you want to do here
then the program will still give you a NullPointerException
. The reason
for this is that in the second line above, you will have declared a local variable
named smiley
and set it to a new instance of UpgradedSmiley
.
However, you were already given a variable named smiley
. If you look
deeper at the code in SmileyMain.java
you will see that the variable
smiley
(the one that was already given to you) is used inside the method
showSmiley
. If you declare a local variable smiley
inside
the initializeSmiley
and modify that variable, those changes will not
be seen in the other methods in the SmileyMain
class.
Step 2 said to add the drawing code to the draw methods in UpgradedSmiley.java
.
The code for the drawFace
method was already filled in for you. We can find the
corresponding code for the other draw methods in Smiley.java
from Lab 3. If you look at the paint
method from
that lab, you will see:
public void paint(Graphics graphics)
{
// Draw face circle:
graphics.setColor(Color.YELLOW);
graphics.fillOval(X_FACE, Y_FACE, FACE_DIAMETER, FACE_DIAMETER);
graphics.setColor(Color.BLACK);
graphics.drawOval(X_FACE, Y_FACE, FACE_DIAMETER, FACE_DIAMETER);
// Draw eyes:
graphics.setColor(eyeColor);
graphics.fillOval(X_RIGHT_EYE, Y_RIGHT_EYE, EYE_WIDTH, EYE_HEIGHT);
graphics.fillOval(X_LEFT_EYE, Y_LEFT_EYE, EYE_WIDTH, EYE_HEIGHT);
// Draw nose:
graphics.setColor(Color.BLACK);
graphics.fillOval(xNose, Y_NOSE, noseDiameter, noseDiameter);
// Draw mouth:
graphics.setColor(Color.RED);
graphics.drawArc(X_MOUTH, Y_MOUTH, MOUTH_WIDTH, MOUTH_HEIGHT,
mouthStartAngle, MOUTH_DEGREES_SHOWN);
}
You had to copy the code from this method into the corresponding draw methods
in the UpgradedSmiley
class. This leads to this code (comments
omitted here, see solution .java
files):
private void drawNose(Graphics graphics)
{
graphics.setColor(Color.BLACK);
graphics.fillOval(xNose, Y_NOSE, noseDiameter, noseDiameter);
}
private void drawMouth(Graphics graphics)
{
graphics.setColor(Color.RED);
graphics.drawArc(X_MOUTH, Y_MOUTH, MOUTH_WIDTH, MOUTH_HEIGHT,
mouthStartAngle, MOUTH_DEGREES_SHOWN);
}
private void drawEyes(Graphics graphics)
{
graphics.setColor(eyeColor);
graphics.fillOval(X_RIGHT_EYE, Y_RIGHT_EYE, EYE_WIDTH, EYE_HEIGHT);
graphics.fillOval(X_LEFT_EYE, Y_LEFT_EYE, EYE_WIDTH, EYE_HEIGHT);
}
Step 3 asked you to call the draw methods from the paintComponent
method. Because the draw methods are in the same class as the paintComponent
method, we do not need to specify any object to call the method on. When we call a method,
it is assumed to be called on the current object. Also, note that the paintComponent
method takes a variable of type Graphics
as a parameter. Each of the
draw methods also take a variable of type Graphics
as a parameter. This means
that you need to pass a variable of type Graphics
to each of the draw methods.
Inside the paintComponent
method, you have access to one: the
paintComponent
method's single parameter, graphics
. This leads
to the following code which calls each of the draw methods from inside the paintComponent
method:
public void paintComponent(Graphics graphics)
{
super.paintComponent(graphics);
// ::: CALL THE METHODS TO DRAW THE FACE, NOSE, EYES, AND MOUTH HERE
drawFace(graphics);
drawNose(graphics);
drawEyes(graphics);
drawMouth(graphics);
}
Step 4 said to ask the user how to change the smiley face, and to call the appropriate
set methods on your instance of UpgradedSmiley
to change the face. You were
also given variables that you were to use in your code:
String eyeColor = "black";
int noseSize = 1;
boolean shouldSmile = false;
Scanner keyboard = new Scanner(System.in);
We have read input from the user in other programs; this time around it is not any different.
The only thing to make sure of was the Gotcha in the book about the next
and nextLine
methods. We can read the necessary input from the user as follows:
// ::: PROMPT THE USER FOR INPUT AND READ INPUT HERE
System.out.println("What eye color would you like? (red, green, or blue)");
eyeColor = keyboard.next();
System.out.println("How big would you like the nose? (1-4)");
noseSize = keyboard.nextInt();
System.out.println("Would you like the smiley to smile? (yes, no)");
shouldSmile = (keyboard.next().equalsIgnoreCase("yes"));
The last line above will read the next item from the input (keyboard.next()
), then check
if that input equals "yes"
(ignoring case). Everything to the right of
the =
sign in this line of code is a Boolean expression -- its value is true
if the string is "yes"
and false
otherwise. I did not specifically
check for "no"
here. shouldSmile
is set to the value of the
Boolean expression.
Then, at the bottom of the initializeSmiley
method, you had to call
the set methods on your instance of UpgradedSmiley
, smiley
:
// ::: CALL THE APPROPRIATE METHODS ON smiley TO SET THE
// EYE COLOR, NOSE SIZE, AND SMILING OR FROWNING MOUTH
smiley.setEyeColor(eyeColor);
smiley.setNoseSize(noseSize);
smiley.setMouth(shouldSmile);
Note that all of these methods are called on the smiley
object. Note also
that the arguments passed to each method match the types of the parameters of each method
as specified in the UpgradedSmiley
class.
Step 5, the last step, asked you to fill in the set methods in UpgradedSmiley
,
noting that most of your code could come from your own Lab 3 assignment. It is important
to make sure that the code that you put in each method does what the comments above each
method say to do -- remember that the comments are also part of the interface that a
programmer using the UpgradedSmiley
class needs to know about. The comments
tell the programmer what a method is supposed to do; the body of a method should
follow the documentation.
The setMouth
method:
public void setMouth(boolean smile)
{
if (smile)
mouthStartAngle = 180;
else
mouthStartAngle = 0;
}
Note that the comments (in UpgradedSmiley.java
) above the setMouth
method say the smiley should smile if the parameter smile
is true
,
and the smiley should frown if the parameter smile
is false
.
The setEyeColor
method:
public void setEyeColor(String color)
{
if (color.equalsIgnoreCase("red"))
eyeColor = Color.RED;
else if (color.equalsIgnoreCase("green"))
eyeColor = Color.GREEN;
else if (color.equalsIgnoreCase("blue"))
eyeColor = Color.BLUE;
else
eyeColor = Color.WHITE;
}
The setNoseSize
method:
public void setNoseSize(int size)
{
if ((size >= 1) && (size <= 4))
{
int center = xNose + noseDiameter / 2;
noseDiameter *= size;
xNose = center - noseDiameter / 2;
}
}
The comments for setNoseSize
were not specific about what to do
if the size parameter was > 4 or < 1, so just about anything reasonable was
accepted.