160 likes | 292 Views
Dragging Images. MouseListener mouseClicked mouseEntered mouseExited mousePressed mouseReleased All are public void All take one parameter, a MouseEvent. MouseMotionListener mouseMoved mouseDragged Both are public void Both take one parameter, a MouseEvent. Getting mouse events.
E N D
MouseListener mouseClicked mouseEntered mouseExited mousePressed mouseReleased All are public void All take one parameter, a MouseEvent MouseMotionListener mouseMoved mouseDragged Both are public void Both take one parameter, a MouseEvent Getting mouse events
Interfaces and Adapters • MouseListener and MouseMotionListener are interfaces • When you implement an interface, you must supply bodies for all of its declared methods • MouseAdapter and MouseMotionAdapter implement these interfaces, with empty bodies • You can extend an adapter class and supply only the methods you need
Images and Components • What you would like to do is to attach listeners to your images • What you can do is attach listeners to Components • An image is not a Component • An "image" has no real existence once it is drawn--it's just pixels • You need to attach your listeners to the Component that your images are drawn in
Detecting clicks on images I • Attach a mouse listener to your Component (the one the image is drawn in) • When one of your listener methods is called, it is given a MouseEvent • The MouseEvent has methods getX() and getY() that you can use to find the mouse position • The mouse coordinates are relative to the Component (just like your image coordinates!)
Detecting clicks on images II • Your image is drawn starting from some X-Y coordinates; these are the top left corner of the image • The mouse X and Y are within the image if: • imageX <= mouseX <= (imageX + imageWidth) • imageY <= mouseY <= (imageY + imageHeight) • You probably want to arrange your code so that if you click over two images simultaneously, only one is chosen
Choosing methods • We don't need all the methods, so we'll use the Adapter classes rather than the interfaces • We obviously want to use mouseDragged from MouseMotionAdapter • mouseDragged is not enough, because we don't want dragging across an image to do anything • It's convenient to use mousePressed to check for starting a drag, and mouseReleased to end one • These are defined in MouseAdapter
Starting and stopping a drag view.addMouseListener(new MouseAdapter( ) { public void mousePressed(MouseEvent event) { ...code... } public void mouseReleased(MouseEvent event) { ...code... } } );
Starting a drag public void mousePressed(MouseEvent event) { // Get mouse position int mouseX = event.getX(); int mouseY = event.getY(); // Check whether the mouse is inside the image if (mouseX >= imageX && mouseX <= imageX + imageWidth && mouseY >= imageY && mouseY <= imageY + imageHeight) draggingImage = true; }
Stopping a drag public void mouseReleased(MouseEvent event) { draggingImage = false; }
Dragging I view.addMouseMotionListener(new MouseMotionAdapter( ) { public void mouseDragged(MouseEvent event) { ...code... } });
Dragging II public void mouseDragged(MouseEvent event) { // Get mouse position int mouseX = event.getX(); int mouseY = event.getY(); if (draggingImage) { // Center image over mouse position imageX = mouseX - (imageWidth / 2); imageY = mouseY - (imageHeight / 2); } }
Jumping images • When we click anywhere on the image, the image is centered under the mouse position • If you don't click near the center of the image, it appears to "jump" to the mouse • Disadvantage: interface doesn't seem as "smooth" • Advantage: you get definite feedback • Advantage: you aren't dragging by the edge • Can be "corrected" by some simple arithmetic
Runaway images • My test code "catches" a moving image • We only get to mouseDragged when the mouse button is held down and the mouse is moving • If the mouse stops moving, the image "runs away" • To correct: check whether the image is being dragged before attempting to move it • This is not a problem for stationary images
A final note: Baklava • In Baklava, you can attach mouseUp, mouseDown, and mouseDrag methods to Sprites • Baklava does this by attaching the Java methods just described to the Playfield (Container component), then doing the same sort of work as we've just done • Using a toolkit like Baklava is very convenient, but sometimes you have to get "under the hood" • Image dragging in Baklava isn't perfect