Question
Modify the NervousShapes so that it displays equilateral triangles as well as circles and rectangles. You will need to define a Triange class containing a
Modify the NervousShapes so that it displays equilateral triangles as well as circles and rectangles. You will need to define a Triange class containing a single instance variable, representing the length of one of the triangles sides. Have the program create circles, rectangles, and triangles with equal probability.
This is the NervousShapes program
// Program name: NervousShapes
// This code is adapted from K. N. King: Java Programming: from the Beginning, 1st edition
//
// Displays a frame containing a random mixture of circles
// and rectangles with random colors, sizes, and positions.
// The shapes periodically change position, with the
// direction of motion chosen randomly for each shape. The
// new x coordinate for each shape will either be the same
// as the old x coordinate, one pixel smaller, or one pixel
// larger; the new y coordinate will be computed in a
// similar manner. Shapes will be constrained so that they
// do not move outside the drawing area.
package NervousShapes;
import java.awt.*;
public class NervousShapes {
// Constants
private static final int DELAY = 10;
// Animation delay (milliseconds)
private static final int MAX_SIZE = 20;
// Maximum width and height of a shape
private static final int MIN_SIZE = 10;
// Minimum width and height of a shape
private static final int NUM_SHAPES = 50;
// Number of shapes
private static final int WINDOW_SIZE = 200;
// Width and height of drawable portion of frame
private static final int CHANGE_RANGE = 1;
// how far the new position can be from the previous position
private static DrawingPanel panel;
private static Graphics g;
// Graphics context for frame
private static Shape shapes[] = new Shape[NUM_SHAPES];
// Array of shapes
public static void main(String[] args) {
createWindow();
createShapes();
animateShapes();
}
///////////////////////////////////////////////////////////
// NAME: createWindow
// BEHAVIOR: Creates a frame labeled "Nervous Shapes",
// displays the frame, and sets the size of
// the frame (using the WINDOW_SIZE class
// variable). Assigns the frame to the df
// class variable, and assigns the frame's
// graphics context to the g class variable.
// PARAMETERS: None
// RETURNS: Nothing
///////////////////////////////////////////////////////////
private static void createWindow() {
// Create the drawing panel
panel = new DrawingPanel(WINDOW_SIZE, WINDOW_SIZE);
// Get the graphics context
g = panel.getGraphics();
}
///////////////////////////////////////////////////////////
// NAME: createShapes
// BEHAVIOR: Creates enough Circle and Rectangle objects
// to fill the shapes array. Each shape has a
// random color, size, and position. The height
// and width of each shape must lie between
// MIN_SIZE and MAX_SIZE (inclusive). The
// position is chosen so that the shape is
// completely within the drawing area.
// PARAMETERS: None
// RETURNS: Nothing
///////////////////////////////////////////////////////////
private static void createShapes() {
for (int i = 0; i < shapes.length; i++) {
// Select a random color
int red = generateRandomInt(0, 255);
int green = generateRandomInt(0, 255);
int blue = generateRandomInt(0, 255);
Color color = new Color(red, green, blue);
// Decide whether to create a circle or a rectangle
if (Math.random() < 0.5) {
// Generate a circle with a random size and position
int diameter = generateRandomInt(MIN_SIZE, MAX_SIZE);
int x = generateRandomInt(0, WINDOW_SIZE - diameter);
int y = generateRandomInt(0, WINDOW_SIZE - diameter);
shapes[i] = new Circle(x, y, color, diameter);
} else {
// Generate a rectangle with a random size and
// position
int width = generateRandomInt(MIN_SIZE, MAX_SIZE);
int height = generateRandomInt(MIN_SIZE, MAX_SIZE);
int x = generateRandomInt(0, WINDOW_SIZE - width);
int y = generateRandomInt(0, WINDOW_SIZE - height);
shapes[i] = new Rectangle(x, y, color, width, height);
}
}
}
///////////////////////////////////////////////////////////
// NAME: animateShapes
// BEHAVIOR: Establishes an infinite loop in which the
// shapes are animated. During each loop
// iteration, the drawing area is cleared and
// the shapes are then drawn at new positions.
// The new x and y coordinates for each shape
// will either be the same as the old ones,
// one pixel smaller, or one pixel larger. A
// shape is not moved if doing so would cause
// any portion of the shape to go outside the
// drawing area. At the end of each animation
// cycle, there is a brief pause, which is
// controlled by the delay constant.
// PARAMETERS: None
// RETURNS: Nothing
///////////////////////////////////////////////////////////
private static void animateShapes() {
while (true) {
// Clear drawing area
g.setColor(Color.white);
g.fillRect(0, 0, WINDOW_SIZE - 1, WINDOW_SIZE - 1);
for (int i = 0; i < shapes.length; i++) {
// Change the x coordinate for shape i
int dx = generateRandomInt(-CHANGE_RANGE, +CHANGE_RANGE);
int newX = shapes[i].getX() + dx;
if (newX >= 0 &&
newX + shapes[i].getWidth() < WINDOW_SIZE)
shapes[i].move(dx, 0);
// Change the y coordinate for shape i
int dy = generateRandomInt(-CHANGE_RANGE, +CHANGE_RANGE);
int newY = shapes[i].getY() + dy;
if (newY >= 0 &&
newY + shapes[i].getHeight() < WINDOW_SIZE)
shapes[i].move(0, dy);
// Draw shape i at its new position
shapes[i].draw(g);
}
panel.sleep(DELAY);
}
}
///////////////////////////////////////////////////////////
// NAME: generateRandomInt
// BEHAVIOR: Generates a random integer within a
// specified range.
// PARAMETERS: min - the lower bound of the range
// max - the upper bound of the range
// RETURNS: A random integer that is greater than or
// equal to min and less than or equal to max
///////////////////////////////////////////////////////////
private static int generateRandomInt(int min, int max) {
return (int) ((max - min + 1) * Math.random()) + min;
}
}
Circle class is BELOW
// Represents a circle that can be displayed in a graphics // context // This code is adapted from K. N. King: Java Programming: from the Beginning, 1st edition
package NervousShapes;
import java.awt.*;
public class Circle extends Shape { // Instance variables private int diameter;
// Constructor public Circle(int x, int y, Color color, int diameter) { super(x, y, color); this.diameter = diameter; } // Instance methods public void draw(Graphics g) { g.setColor(getColor()); g.fillOval(getX(), getY(), diameter, diameter); }
public int getHeight() { return diameter; }
public int getWidth() { return diameter; } }
Rectangle Cass is BELOW
// Represents a rectangle that can be displayed in a graphics // context // This code is adapted from K. N. King: Java Programming: from the Beginning, 1st edition
package NervousShapes;
import java.awt.*;
public class Rectangle extends Shape { // Instance variables private int width; private int height;
// Constructor public Rectangle(int x, int y, Color color, int width, int height) { super(x, y, color); this.width = width; this.height = height; } // Instance methods public void draw(Graphics g) { g.setColor(getColor()); g.fillRect(getX(), getY(), width, height); }
public int getHeight() { return height; }
public int getWidth() { return width; } }
Shape class is BELOW
// Represents a geometric shape that can be displayed in a // graphics context // This code is adapted from K. N. King: Java Programming: from the Beginning, 1st edition
package NervousShapes;
import java.awt.*;
public abstract class Shape { // Instance variables private int x; private int y; private Color color;
// Constructor protected Shape(int x, int y, Color color) { this.x = x; this.y = y; this.color = color; } // Abstract methods public abstract void draw(Graphics g); public abstract int getHeight(); public abstract int getWidth();
// Other instance methods public Color getColor() { return color; }
public int getX() { return x; }
public int getY() { return y; } public void move(int dx, int dy) { x += dx; y += dy; }
public void setColor(Color color) { this.color = color; } }
DrawingPanel class is BELOW
/* Stuart Reges and Marty Stepp 07/01/2005
The DrawingPanel class provides a simple interface for drawing persistent images using a Graphics object. An internal BufferedImage object is used to keep track of what has been drawn. A client of the class simply constructs a DrawingPanel of a particular size and then draws on it with the Graphics object, setting the background color if they so choose.
To ensure that the image is always displayed, a timer calls repaint at regular intervals. */ package NervousShapes;
import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.imageio.*; import javax.swing.*; import javax.swing.event.*;
public class DrawingPanel implements ActionListener { public static final int DELAY = 50; // delay between repaints in millis
private static final String DUMP_IMAGE_PROPERTY_NAME = "drawingpanel.save"; private static String TARGET_IMAGE_FILE_NAME = null; private static final boolean PRETTY = true; // true to anti-alias private static boolean DUMP_IMAGE = true; // true to write DrawingPanel to file
private int width, height; // dimensions of window frame private JFrame frame; // overall window frame private JPanel panel; // overall drawing surface private BufferedImage image; // remembers drawing commands private Graphics2D g2; // graphics context for painting private JLabel statusBar; // status bar showing mouse position private long createTime;
static { TARGET_IMAGE_FILE_NAME = System.getProperty(DUMP_IMAGE_PROPERTY_NAME); DUMP_IMAGE = (TARGET_IMAGE_FILE_NAME != null); }
// construct a drawing panel of given width and height enclosed in a window public DrawingPanel(int width, int height) { this.width = width; this.height = height; this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
this.statusBar = new JLabel(" "); this.statusBar.setBorder(BorderFactory.createLineBorder(Color.BLACK));
this.panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0)); this.panel.setBackground(Color.WHITE); this.panel.setPreferredSize(new Dimension(width, height)); this.panel.add(new JLabel(new ImageIcon(image)));
// listen to mouse movement MouseInputAdapter listener = new MouseInputAdapter() { public void mouseMoved(MouseEvent e) { DrawingPanel.this.statusBar.setText("(" + e.getX() + ", " + e.getY() + ")"); }
public void mouseExited(MouseEvent e) { DrawingPanel.this.statusBar.setText(" "); } }; this.panel.addMouseListener(listener); this.panel.addMouseMotionListener(listener);
this.g2 = (Graphics2D)image.getGraphics(); this.g2.setColor(Color.BLACK); if (PRETTY) { this.g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); this.g2.setStroke(new BasicStroke(1.1f)); }
this.frame = new JFrame("Building Java Programs - Drawing Panel"); this.frame.setResizable(false); this.frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { if (DUMP_IMAGE) { DrawingPanel.this.save(TARGET_IMAGE_FILE_NAME); } System.exit(0); } }); this.frame.getContentPane().add(panel); this.frame.getContentPane().add(statusBar, "South"); this.frame.pack(); this.frame.setVisible(true); if (DUMP_IMAGE) { createTime = System.currentTimeMillis(); this.frame.toBack(); } else { this.toFront(); }
// repaint timer so that the screen will update new Timer(DELAY, this).start(); }
// used for an internal timer that keeps repainting public void actionPerformed(ActionEvent e) { this.panel.repaint(); if (DUMP_IMAGE && System.currentTimeMillis() > createTime + 4 * DELAY) { this.frame.setVisible(false); this.frame.dispose(); this.save(TARGET_IMAGE_FILE_NAME); System.exit(0); } }
// obtain the Graphics object to draw on the panel public Graphics2D getGraphics() { return this.g2; }
// set the background color of the drawing panel public void setBackground(Color c) { this.panel.setBackground(c); }
// show or hide the drawing panel on the screen public void setVisible(boolean visible) { this.frame.setVisible(visible); }
// makes the program pause for the given amount of time, // allowing for animation public void sleep(int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) {} }
// take the current contents of the panel and write them to a file public void save(String filename) { String extension = filename.substring(filename.lastIndexOf(".") + 1);
// create second image so we get the background color BufferedImage image2 = new BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_RGB); Graphics g = image2.getGraphics(); g.setColor(panel.getBackground()); g.fillRect(0, 0, this.width, this.height); g.drawImage(this.image, 0, 0, panel);
// write file try { ImageIO.write(image2, extension, new java.io.File(filename)); } catch (java.io.IOException e) { System.err.println("Unable to save image: " + e); } }
// makes drawing panel become the frontmost window on the screen public void toFront() { this.frame.toFront(); } }
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started