CSE190L Sample Final, Spring 2007 handout #28
1. Inheritance, 30 points. You are to rewrite a pair of classes using
inheritance to avoid redundancy. The classes you will rewrite are
subclasses of JPanel that draw and label a particular shape. One draws a
circle and one draws a rectangle, as in the two panels displayed below.
These are just two examples of a family of shapes that we might want to
draw. As with these two, each would be centered within the panel and would
be labeled with a title using an 18-point bold Serif font just below the
figure.
When you compare these two classes, you will find a lot of redundancy. You
are to eliminate the redundant code by creating a superclass for these two
classes called Picture. You should appropriately declare any method as
abstract if the definition of the method varies from one subclass to the
next. All data fields of your classes must be declared to be private,
although you can introduce protected methods.
Below and on the next page are the two classes you are to rewrite.
public class Circle extends JPanel {
private int radius;
public Circle(int radius) {
this.radius = radius;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Font f = new Font("Serif", Font.BOLD, 18);
g2.setFont(f);
int centerX = getWidth()/2;
int centerY = getHeight()/2;
g2.draw(new Ellipse2D.Double(centerX - radius, centerY - radius,
2 * radius, 2 * radius));
g2.fill(new Ellipse2D.Double(centerX, centerY, 3, 3));
String text = "Circle";
FontRenderContext context = g2.getFontRenderContext();
double width =
g2.getFont().getStringBounds(text, context).getWidth();
g2.drawString(text, centerX - (int) (width/2),
centerY + radius + 18);
}
}
public class Rectangle extends JPanel {
private int height;
private int width;
public Rectangle(int height, int width) {
this.height = height;
this.width = width;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Font f = new Font("Serif", Font.BOLD, 18);
g2.setFont(f);
int centerX = getWidth()/2;
int centerY = getHeight()/2;
g2.draw(new Rectangle2D.Double(centerX - width/2,
centerY - height/2, width, height));
g2.draw(new Line2D.Double(centerX - width/2, centerY - height/2,
centerX + width/2, centerY + height/2));
g2.draw(new Line2D.Double(centerX - width/2, centerY + height/2,
centerX + width/2, centerY - height/2));
String text = "Rectangle";
FontRenderContext context = g2.getFontRenderContext();
double width =
g2.getFont().getStringBounds(text, context).getWidth();
g2.drawString(text, centerX - (int) (width/2),
centerY + height/2 + 18);
}
}
Most of the points for this question will be given for eliminating
redundancy, but some points will be given based on the ability to extend
your Picture class without modifying it. For example, it should be possible
to create other picture subclasses (e.g., a triangle, a diamond, a spiral)
without modifying the Picture class itself.
Include the definitions of Picture, Circle and Rectangle below. You do not
have to copy all of the code if you give a clear description of what goes
where.
2. Layout managers, 30 points. You are to write code that structures the
layout managers for a JFrame. This particular JFrame is divided in half
with an upper part and a lower part. The upper part is further divided in
half. In the upper left are a pair of buttons and a panel that contains a
clock. In the upper-right is panel that contains a live image of the bridge
of the Enterprise (from Star Trek). The two buttons should appear stacked
one on top of the other against a cyan background. The buttons should have
their preferred height and width, so that any additional horizontal space
goes to the clock panel. In the lower half of the frame is a panel that
contains a short range scan with a button on top for quitting the
application. Notice that the quit button has its preferred height but fills
the width of the frame. Further notice that there is a black line
separating the top and bottom halves of the frame and in the upper half
there is a black line separating the left and right halves. These black
lines should be 5 pixels wide. If the frame is made larger, additional
space goes to the clock, the image of the bridge and the short range scan.
Below is a snapshot of how the frame should look.
Assume that the following variables have been defined:
clock the panel that draws the clock
bridge the panel that shows the image of the bridge
shortScan the panel that draws the short range scan
save the save button
rescan the rescan button
quit the quit button
You are to write code that would be included in the frame's constructor to
lay out these components properly. Note that you only have to do the
layout. You don't have to create the objects, attach listeners or otherwise
solve the overall problem. The only objects you should create are the
layout containers and any layout managers. You should set background colors
appropriately. You may assume the frame class has the following general
structure:
public class TrekFrame {
private JFrame frame;
// other fields (not shown)
public TrekFrame() {
frame = new JFrame();
frame.setSize(450, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("cse190L scan monitor");
// code to set up other fields (not shown)
// your code here
}
public void start() {
frame.setVisible(true);
}
// other methods (not shown)
}
You may define private methods that would be called by the code you are
adding to the constructor.
3. Classes, 30 points. Define a class called ElapsedTime for storing elapsed
times. It should have the following constructor:
public ElapsedTime(int hours, int minutes, int seconds)
// post: constructs a date object for given hours, minutes, seconds
The constructor should throw an IllegalArgumentException if any of the thre
parameters is negative. It should be possible to add the value of a second
time object using the following method:
public void add(ElapsedTime t)
// post: adds the given time to this time
In doing so, it's possible that the minutes or seconds can "overflow". For
example, if one time has 32 seconds and the other has 47, the sum is 79, but
that should be reported as 1 minute and 19 seconds. So your class has to
take care of seconds overflowing into minutes and minutes overflowing into
hours. Hours can be any value. You need to handle the overflow problem
even if it happens in the constructor (i.e., if someone constructs an object
with something like 84 seconds, you have to change that to 24 seconds and
increment the minutes by 1).
You should include methods getHours(), getMinutes() and getSeconds() to
obtain the individual components. The getMinutes() and getSeconds() methods
should always return integers in the range of 0 to 59. You should also
include a toString method that converts it to the familiar notation of
hours:minutes:seconds, again with minutes and seconds in the range of 0 to
59. Minutes and seconds should always be reported as two characters. For
example, you'd report "3:05:07" to indicate 3 hours, 5 minutes and 7 seconds
rather than "3:5:7". Finally, your class should implement the Comparable
interface, ordering the times from shortest to longest, and should override
the equals and hashCode methods.
4. Programming, 10 points. Suppose that a ListItem class has been defined as
follows:
class ListItem {
public String name;
public boolean hidden;
public ListItem(String name) {
this.name = name;
hidden = false;
}
public void setHidden(boolean hidden) {
this.hidden = hidden;
}
public boolean isHidden() {
return hidden;
}
public String getName() {
return name;
}
}
This defines a list item that can store a single string and that can be set
to be hidden (true or false). Notice that by default, list items are not
hidden.
You are to define a class List that includes the following public methods:
public List(String name)
constructs an empty list with given name
public void add( item)
adds given item to the end of the list
public int length()
returns the current length (ignoring any hidden values)
public int size()
returns the current length (including all values)
public get(int index)
returns the item at the given index
public void setHidden(boolean hidden)
sets whether or not this list is hidden
public boolean isHidden()
returns true if this list is hidden, otherwise returns false
public String getName()
returns the name of this list
Part of this question involves design. The descriptions above mention a type
"". You are to decide what this type should be. Whatever you
chose, it has to be possible for a list to contain a combination of list items
and lists. In other words, the add method above could be called with a
parameter either of type List or of type ListElement. This allows you to nest
lists as deeply as you want to (e.g., a list of lists of list items).
The size and get methods don't pay attention to whether or not values are
hidden, but in computing the length of a list, you are to ignore any hidden
elements. For example, if a list stores 7 values, 2 of which are currently
hidden, then the length should be reported as 5 even though the size would be
reported as 7.
Half of the points for this question will be awarded on the basis of your
ability to structure your solution in such a way that there is minimal code
duplication. This may lead you to want to modify the ListElement class. For
example, you might want it to have a different inheritance relationship or you
might want to move some of its methods or fields elsewhere.
Briefly describe below any changes you want to make to the ListElement class
and provide your solution to class List below.