import java.applet.Applet; import java.awt.Image; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.Color; import java.awt.Font; import java.awt.Event; // Applet Life Cycle: // init(): called one time so that an applet can be loaded (initialized) // (when a Web browser page is first loaded) // start(): should be called next, and may be called multiple times if the // applet needs to be started or restarted // stop(): should be called to stop the applet from running, and may be // called multiple times in the life cycle of the applet // destroy(): called one time to unload the applet (when the Web browser // window is closed) // The above methods are built into the 'applet' class, but can be overridden public class GraphicsMoveAndCollideWithMouseAndApplet extends Applet { Image Buffer; Graphics gBuffer; Rectangle rectRed, rectBlue; int width, height; boolean mouseInside, collide; public void init() { mouseInside = false; collide = false; width = 300; height = 280; Buffer = createImage(width, height); gBuffer = Buffer.getGraphics(); // Create the red (stationary) rectangle rectRed = new Rectangle(120, 115, 60, 50); // Since the coordinates of the blue (moving) rectangle are not // yet known, it is created using a different constructor, one // that requires only the size of the shape rectBlue = new Rectangle(40, 40); } // This method creates/updates the images to be displayed in the applet; // note that nothing is actually displayed here, though, as all of the // drawing of the graphics takes place via the 'paint' method public void SetImage() { // Draw/Redraw the applet background so that previous instances of // the blue rectangle are not left behind and visible on the applet gBuffer.setColor(Color.WHITE); gBuffer.fillRect(0, 0, width, height); // Draw/Redraw the red rectangle (even though it doesn't move) gBuffer.setColor(Color.RED); gBuffer.fillRect(rectRed.x, rectRed.y, rectRed.width, rectRed.height); if (mouseInside) { // Draw/Redraw the blue rectangle (under the mouse pointer) gBuffer.setColor(Color.BLUE); gBuffer.fillRect(rectBlue.x, rectBlue.y, rectBlue.width, rectBlue.height); } // Set the font and display the appropriate message inside the applet gBuffer.setColor(Color.BLACK); gBuffer.setFont(new Font("Helvetica", Font.BOLD, 16)); if (!mouseInside) gBuffer.drawString("Move the mouse inside the applet...", 15, 20); if (collide) gBuffer.drawString("Collision Detected!", 75, 20); } // Check if the mouse pointer is over (inside) the applet public boolean mouseEnter(Event event, int x, int y) { mouseInside = true; return true; } // Check if the mouse pointer is not in (outside) the applet public boolean mouseExit(Event event, int x, int y) { mouseInside = false; repaint(); return true; } // Check if the user has moved the mouse pointer public boolean mouseMove(Event event, int x, int y) { // Keep the blue rectangle under the mouse pointer rectBlue.setLocation(x - rectBlue.width / 2, y - rectBlue.height / 2); // Check for a collision of the red and blue rectangles collide = rectRed.intersects(rectBlue); SetImage(); repaint(); return true; } // The 'update' method is automatically called in response to a 'repaint' // request, or in response to a portion of the applet being uncovered or // displayed for the first time. The method's sole argument is an instance // of the 'Graphics' class. The Graphics instance is valid only within the // context of the 'update' method (and any methods that it calls), but is // disposed of soon after the 'update' method returns. // Since the built-in (default) implementation of the 'update' method erases // the background of the applet and then calls the 'paint' method, a new // 'update' method is created below to override the default 'update' method // so that it does NOT erase the background of the applet. Instead, the // new 'update' method will just call the 'paint' method, which can be set // to handle any erasing that needs to take place. public void update(Graphics g) { paint(g); } // The 'paint' method is called from the 'update' method, and is responsible for // actually drawing the graphics. The method's sole argument is an instance of // the 'Graphics' class. The built-in (default) implementation of the 'paint' // method provided by class 'Component' does nothing, so a new 'paint' method // should always be created to override the default method. // Calls to the 'paint' method can be generated spontaneously by the user's // environment (GUI) or directly by the program (usually via the 'repaint' or // 'update' methods). There are several situations in which calls are // generated spontaneously: // 1) an applet is covered by another applet or a window and is then re-exposed, // at which point the 'paint' method is called to reconstruct the // previously-covered parts of the uncovered applet // 2) the method 'init' has been called and has just finished // 3) a user returns to a Web browser page which contains an applet (provided // the applet is at least partially exposed) // In general, the 'paint' method should not be called directly, but should // instead be called through the 'repaint' method. This way, the abstract // window toolkit (AWT) system thread will take care of accepting input events // and calling the 'paint' method. Programmers should leave the 'paint' // calls to this thread. public void paint(Graphics g) { setSize(width, height); SetImage(); g.drawImage(Buffer, 0, 0, this); } // The built-in (default) method 'repaint' does not call (invoke) the 'paint' // method directly. Instead, it SCHEDULES a call to the 'update' method which, // in turn, calls the 'paint' method (unless it has been overridden, in which // case it may or may not call the 'paint' method). The reason for this complex // process is Java's support for concurrent programming (via threads). // The 'repaint' method merely REQUESTS that the abstract window toolkit (AWT) // thread place a call to the method 'update' to repaint a component. It then // returns immediately. This is called asynchronous behavior. How the AWT // thread acts is up to it, and if the programming is not handled carefully, this // can lead to problems, such as multiple 'repaint' requests unintentionally // being combined into a single request. // When the 'repaint' method is called, the calling method may request that // repainting occur as soon as possible, or it may specify a period of time (in // milliseconds), which should cause the painting operation to occur when the // period of time has elapsed. The calling method may also specify that only a // portion of a component be repainted. This technique is useful if the paint // operation is time-consuming, or if only a portion of the display needs to be // repainted. // To reduce the time required to repaint a display, the AWT takes two shortcuts: // First, the AWT repaints only those components that need repainting, either // because they have been uncovered, or because a request was made to repaint // them. Second, if a component was covered and then uncovered, the AWT repaints // only the portion of the component that was previously covered. }