/* An applet showing a red square and a blue square that the user can drag with the mouse. The user can drag a square off the applet and drop them. It will jump back to its starting point. This applet does uses double buffering. Double-buffer is handled by the update() method. NonDoubleBufferedDrag is a non-double-buffered version of this applet. */ import java.awt.*; import java.awt.event.*; import java.applet.*; public class DoubleBufferedDrag extends Applet implements MouseListener, MouseMotionListener { int x1, y1; // Coords of top-left corner of the red square. int x2, y2; // Coords of top-left corner of the blue square. /* Some variable used for double-buffering */ Image OSC; // The off-screen canvas (created and used in update()). int widthOfOSC, heightOfOSC; // Current widht and height of OSC. These // are checked against the size of the applet, // to detect any change in the applet's size. // If the size has changed, a new OSC is created. /* Some variables used during dragging */ boolean dragging; // Set to true when a drag is in progress. boolean dragRedSquare; // True if red square is being dragged, false // if blue square is being dragged. int offsetX, offsetY; // Offset of mouse-click coordinates from // top-left corner of the square that was // clicked. public void init() { // Initialize the applet by putting the squares in a // starting position, setting a background color, and // setting the applet to listen for mouse events on itself. x1 = 10; y1 = 10; x2 = 50; y2 = 10; setFont( new Font("Serif", Font.BOLD,14) ); setBackground(Color.lightGray); addMouseListener(this); addMouseMotionListener(this); } public void update(Graphics g) { // To implement double-buffering, the update method calls paint to // draw the contents of the applet on an off-screen canvas. Then // the canvas is copied onto the screen. This method is responsible // for creating the off-screen canvas. It will make a new OSC if // the size of the applet changes. if (OSC == null || widthOfOSC != getSize().width || heightOfOSC != getSize().height) { // Create the OSC, or make a new one if applet size has changed. OSC = null; // (If OSC already exists, this frees up the memory.) OSC = createImage(getSize().width, getSize().height); widthOfOSC = getSize().width; heightOfOSC = getSize().height; } Graphics OSG = OSC.getGraphics(); // Graphics context for drawing to OSC. OSG.setColor(getBackground()); OSG.fillRect(0, 0, widthOfOSC, heightOfOSC); OSG.setColor(getForeground()); OSG.setFont(getFont()); paint(OSG); // Draw applet contents to OSC. g.drawImage(OSC,0,0,this); // Copy OSC to screen. } public void paint(Graphics g) { // Draw the two squars and a black frame around the applet. g.setColor(Color.red); g.fillRect(x1, y1, 30, 30); g.setColor(Color.blue); g.fillRect(x2, y2, 30, 30); g.setColor(Color.black); g.drawRect(0, 0, getSize().width - 1, getSize().height - 1); g.drawString("Double-buffered", 10, getSize().height - 10); } public void mousePressed(MouseEvent evt) { // Respond when the user presses the mouse on the applet. // Check which square the user clicked, if any, and start // dragging that square. if (dragging) // Exit if a drag is already in progress. return; int x = evt.getX(); // Location where user clicked. int y = evt.getY(); if (x >= x2 && x < x2+30 && y >= y2 && y < y2+30) { // It's the blue square (which should be checked first, // since it's in front of the red square.) dragging = true; dragRedSquare = false; offsetX = x - x2; // Distance from corner of square to click point. offsetY = y - y2; } else if (x >= x1 && x < x1+30 && y >= y1 && y < y1+30) { // It's the red square. dragging = true; dragRedSquare = true; offsetX = x - x1; // Distance from corner of square to click point. offsetY = y - y1; } } public void mouseReleased(MouseEvent evt) { // Dragging stops when user releases the mouse button. // If sqaure is (almost) off the screen, move it back to // its starting point. dragging = false; if (dragRedSquare) { if (x1 + 30 < 3 || x1 > getSize().width - 3 || y1 + 30 < 3 || y1 > getSize().height - 3) { x1 = 10; y1 = 10; } } else { if (x2 + 30 < 3 || x2 > getSize().width - 3 || y2 + 30 < 3 || y2 > getSize().height - 3) { x2 = 50; y2 = 10; } } repaint(); } public void mouseDragged(MouseEvent evt) { // Respond when the user drags the mouse. If a square is // not being dragged, then exit. Otherwise, change the position // of the square that is being dragged to match the position // of the mouse. Note that the corner of the square is place // in the same postion with respect to the mouse that it had // when the user started dragging it. if (dragging == false) return; int x = evt.getX(); int y = evt.getY(); if (dragRedSquare) { // Move the red square. x1 = x - offsetX; y1 = y - offsetY; } else { // Move the blue square. x2 = x - offsetX; y2 = y - offsetY; } repaint(); } public void mouseMoved(MouseEvent evt) { } public void mouseClicked(MouseEvent evt) { } public void mouseEntered(MouseEvent evt) { } public void mouseExited(MouseEvent evt) { } } // end class DragTwoSquares