CSE190L Key to Sample Final, Spring 2007 handout #29 1. One possible solution appears below. public abstract class Picture extends JPanel { private String text; private int halfHeight; public Picture(String text, int halfHeight) { this.text = text; this.halfHeight = halfHeight; } public abstract void paintPicture(Graphics2D g, int centerX, int centerY); 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; paintPicture(g2, centerX, centerY); FontRenderContext context = g2.getFontRenderContext(); double width = g2.getFont().getStringBounds(text, context).getWidth(); g2.drawString(text, centerX - (int) (width/2), centerY + halfHeight + 18); } } public class Circle extends Picture { private int radius; public Circle(int radius) { super("Circle", radius); this.radius = radius; } public void paintPicture(Graphics2D g2, int centerX, int centerY) { g2.draw(new Ellipse2D.Double(centerX - radius, centerY - radius, 2 * radius, 2 * radius)); g2.fill(new Ellipse2D.Double(centerX, centerY, 3, 3)); } } public class Rectangle extends Picture { private int height; private int width; public Rectangle(int height, int width) { super("Rectangle", height/2); this.height = height; this.width = width; } public void paintPicture(Graphics2D g2, int centerX, int centerY) { 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)); } } 2. One possible solution appears below. frame.setLayout(new GridLayout(2, 1, 5, 5)); frame.setBackground(Color.BLACK); JPanel upperLeft = new JPanel(); upperLeft.setLayout(new BorderLayout()); JPanel buttons = new JPanel(); buttons.setLayout(new GridLayout(2, 1)); buttons.add(save); buttons.add(rescan); JPanel buttonsOuter = new JPanel(); buttonsOuter.add(buttons); buttonsOuter.setBackground(Color.CYAN); upperLeft.add(buttonsOuter, BorderLayout.NORTH); upperLeft.add(clock, BorderLayout.CENTER); JPanel upper = new JPanel(); upper.setLayout(new GridLayout(1, 2, 5, 5)); upper.setBackground(Color.BLACK); upper.add(upperLeft); upper.add(bridge); JPanel lower = new JPanel(); lower.setLayout(new BorderLayout()); lower.add(quit, BorderLayout.NORTH); lower.add(shortScan, BorderLayout.CENTER); frame.add(upper); frame.add(lower); 3. One possible solution appears below. public class ElapsedTime implements Comparable<ElapsedTime> { private int seconds; public ElapsedTime(int hours, int minutes, int seconds) { if (hours < 0 || minutes < 0 || seconds < 0) throw new IllegalArgumentException(); this.seconds = seconds + 60 * (minutes + 60 * hours); } public int getSeconds() { return seconds % 60; } public int getMinutes() { return seconds/60 % 60; } public int getHours() { return seconds / 3600; } public void add(ElapsedTime t) { seconds += t.seconds; } public String toString() { String result = getHours() + ":"; int min = getMinutes(); int sec = getSeconds(); if (min < 10) result += "0" + min + ":"; else result += min + ":"; if (sec < 10) result += "0" + sec; else result += sec; return result; } public int compareTo(ElapsedTime other) { return seconds - other.seconds; } public int hashCode() { return 10000 * seconds; } public boolean equals(Object other) { if (!(other instanceof ElapsedTime)) return false; else return (compareTo((ElapsedTime) other) == 0); } } 4. There are several possible solutions. You could, for example, define an interface that both ListItem and List implement that would mention the getHidden method. That would lead to significant code duplication. A better solution would be to have an abstract class that each extends so that you can factor out common code. Even better is to have List extend ListElement. That way it inherits all of its fields and methods and the two types are automatically compatible because a List "is a" ListItem. This is the pattern used with Menu/MenuItem and JPanel/JComponent which allows you to have menus nested as deeply as you want (menus inside menus inside menus) and panels nested as deeply as you want (panels inside panels inside panels). This technique is known as the composite pattern. Below is the code that would implement this approach. public class List extends ListItem { private ArrayList<ListItem> elements; public List(String name) { super(name); elements = new ArrayList<ListItem>(); } public void add(ListItem element) { elements.add(element); } public int length() { int count = 0; for (ListItem element : elements) if (!element.isHidden()) count++; return count; } public ListItem get(int index) { return elements.get(index); } public int size() { return elements.size(); } }
Stuart Reges
Last modified: Sun Jun 3 19:20:44 PDT 2007