import java.applet.*; import java.awt.*; import java.awt.event.*; public class Kaleidoscope extends Applet implements ActionListener, Runnable { private volatile Thread tickThread = null; private boolean isRunning; private KaleidoscopeCanvas kaleidoscopeCanvas; private Checkbox rectangleCheckbox, squareCheckbox, ellipseCheckbox, circleCheckbox, triangleCheckbox; private Button startStopButton; private static final int WIDTH = 800; private static final int HEIGHT = 500; public void init() { isRunning = false; setLayout(new BorderLayout()); Panel shapePanel = new Panel(); rectangleCheckbox = new Checkbox("Rectangle"); shapePanel.add(rectangleCheckbox); squareCheckbox = new Checkbox("Square"); shapePanel.add(squareCheckbox); ellipseCheckbox = new Checkbox("Ellipse"); shapePanel.add(ellipseCheckbox); circleCheckbox = new Checkbox("Circle"); shapePanel.add(circleCheckbox); triangleCheckbox = new Checkbox("Triangle"); shapePanel.add(triangleCheckbox); startStopButton = new Button("Start"); startStopButton.addActionListener(this); shapePanel.add(startStopButton); add(shapePanel, BorderLayout.NORTH); kaleidoscopeCanvas = new KaleidoscopeCanvas(); add(kaleidoscopeCanvas, BorderLayout.CENTER); } // start a thread : You should leave this method be public void start() { if ((isRunning) && (tickThread == null)) { tickThread = new Thread(this); tickThread.start(); } } // run a thread and update every X milliseconds public void run() { Thread myThread = Thread.currentThread(); while (tickThread == myThread) { // // THIS IS the point where you can generate random shapes, and pass each random shape to the canvas for painting. // A Kaleidoscope should ideally have 4 or 8 mirrored images of the same object. So, if you generate a circle at // position (100,100) in an 800x600 screen, then the same circle should also appear at position (700,100), // (100,500), and (700,500) // It is up to you how you would like to implement this functionality. You can make 4 calls here, and assume the // applet's preset size, e.g. 800x600. // When generating random shapes, make sure that you are only using shapes that have been selected in the UI! // int r = (int)(Math.random() * 5); int x = (int)(Math.random() * (WIDTH >> 1)); int y = (int)(Math.random() * (HEIGHT >> 1)); Color c = new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)); Shape shapeNW, shapeNE, shapeSE, shapeSW; shapeNW = shapeNE = shapeSE = shapeSW = null; int m = 1; if ((r == 0) && (rectangleCheckbox.getState())) { int width = (int)(Math.random() * (WIDTH >> 3)); int height = (int)(Math.random() * (HEIGHT >> 3)); shapeNW = new Rectangle(x, y, width, height, c); shapeNE = new Rectangle(WIDTH - x - width, y, width, height, c); shapeSE = new Rectangle(WIDTH - x - width, HEIGHT - y - height, width, height, c); shapeSW = new Rectangle(x, HEIGHT - y - height, width, height, c); m = 100; } else if ((r == 1) && (squareCheckbox.getState())) { int side = (int)(Math.random() * (HEIGHT >> 3)); shapeNW = new Square(x, y, side, c); shapeNE = new Square(WIDTH - x - side, y, side, c); shapeSE = new Square(WIDTH - x - side, HEIGHT - y - side, side, c); shapeSW = new Square(x, HEIGHT - y - side, side, c); m = 100; } else if ((r == 2) && (ellipseCheckbox.getState())) { int shortAxis = (int)(Math.random() * (HEIGHT >> 3)); int longAxis = (int)(Math.random() * (WIDTH >> 3)); shapeNW = new Ellipse(x, y, longAxis, shortAxis, c); shapeNE = new Ellipse(WIDTH - x - (longAxis << 1), y, longAxis, shortAxis, c); shapeSE = new Ellipse(WIDTH - x - (longAxis << 1), HEIGHT - y - (shortAxis << 1), longAxis, shortAxis, c); shapeSW = new Ellipse(x, HEIGHT - y - (shortAxis << 1), longAxis, shortAxis, c); m = 100; } else if ((r == 3) && (circleCheckbox.getState())) { int radius = (int)(Math.random() * (HEIGHT >> 3)); shapeNW = new Circle(x, y, radius, c); shapeNE = new Circle(WIDTH - x - (radius << 1), y, radius, c); shapeSE = new Circle(WIDTH - x - (radius << 1), HEIGHT - y - (radius << 1), radius, c); shapeSW = new Circle(x, HEIGHT - y - (radius << 1), radius, c); m = 100; } else if (triangleCheckbox.getState()) { int side = (int)(Math.random() * (WIDTH >> 3)); shapeNW = new Triangle(x, y, side, c); shapeNE = new Triangle(WIDTH - x - side, y, side, c); shapeSE = new Triangle(WIDTH - x - side, HEIGHT - y - side, side, c, true); shapeSW = new Triangle(x, HEIGHT - y - side, side, c, true); m = 100; } kaleidoscopeCanvas.drawShape(shapeNW, shapeNE, shapeSE, shapeSW); try { // updates every m milliseconds Thread.sleep(m); } catch (InterruptedException e) { } } } // listen for Start/Stop action: You should leave this method be public void actionPerformed(ActionEvent e) { if (isRunning) { isRunning = false; tickThread = null; startStopButton.setLabel("Start"); } else { isRunning = true; startStopButton.setLabel("Stop"); start(); } } }