Results 1 to 4 of 4
  1. #1
    robbie.26 is offline Member
    Join Date
    Jun 2011
    Posts
    19
    Rep Power
    0

    Default Repositioning components based on mouse position

    Hello, I am implementing a zoom feature for a JPanel that is populated with many smaller JPanels.
    The premise is: when the user spins the mouse scroll wheel the "zoomPercent" is increased/decreased and then all the child components are resized based on their "defaultSize" and the new "zoomPercent" value. This all works fine. Now the problem I've run into is how to get the child components to relocate towards the mouse pointer based on the "zoomPercent" to give the illusion of zooming. I believe the Trig involved requires the use of the AAA Similar Triangle Theorem but I can't quite figure it out. What I have right now \/ is giving me odd results. When I scroll the mouse wheel forward the elements seem to move towards the mouse pointer, but they don't move away from the pointer when I scroll backwards on the scroll wheel. Eventually, after scrolling forwards and backwards a few times the child components will all be perfectly overlapped and jump to the mouse pointer's position when I try scrolling. Any guidance?


    Java Code:
    private int zoomPercent = 100;
    
    public void mouseWheelMoved(MouseWheelEvent e)
    {
        int oldZoomPercent = Math.max(1, zoomPercent);
        int notches = -e.getWheelRotation();
        int increment = 50;
        zoomPercent += increment * notches;
        zoomPercent = Math.max(0, zoomPercent);
    
        //mouse position
        int x = e.getX();
        int y = e.getY();
    
        for (Node node: nodes)
        {
            int newWidth = node.defaultWidth * zoomPercent / 100;
            int newHeight = node.defaultHeight * zoomPercent / 100;
            node.setSize(newWidth, newHeight);
    
            int nodeX = node.getLocation().x;
            int nodeY = node.getLocation().y;
    
            int dx = Math.abs(x - nodeX);
            int dy = Math.abs(y - nodeY);
    
            //distance between component and mouse pointer
            double hyp = Math.sqrt(dx * dx + dy * dy);
    
            //angle of hypotenuse
            double angle = Math.asin(dy / hyp);
    
            //new hypotenuse length
            double newHyp = hyp * zoomPercent / oldZoomPercent;
    
            //horizontal component of hypotenuse
            double sin = Math.sin(angle);
            //vertical component of hypotenuse
            double cos = Math.cos(angle);
    
            //change in horizontal component
            dx = (int) Math.abs(sin * newHyp - sin * hyp);
            //change in vertical component
            dy = (int) Math.abs(cos * newHyp - cos * hyp);
    
            int finalX, finalY = 0;
    
            if (nodeX > x) {
                finalX = x + dx;
            } else {
                finalX = x - dx;
            }
    
            if (nodeY > y) {
                finalY = y + dy;
            } else {
                finalY = y - dy;
            }
    
            node.setLocation(finalX, finalY);
        }
        validate();
    }

  2. #2
    pbrockway2 is offline Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,565
    Rep Power
    12

    Default

    If you want to perform an enlargement whose center is at the mouse position, I'm not sure I would bother with the angle.

    * Find nodeX-x, the x-distance to the node. (Don't Math.abs() it because the sign is important)
    * Multiply this "delta" by the scale factor
    * Add the result back to x to get the new x-position of the node
    * Repeat for y

  3. #3
    robbie.26 is offline Member
    Join Date
    Jun 2011
    Posts
    19
    Rep Power
    0

    Default

    Quote Originally Posted by pbrockway2 View Post
    If you want to perform an enlargement whose center is at the mouse position, I'm not sure I would bother with the angle.

    * Find nodeX-x, the x-distance to the node. (Don't Math.abs() it because the sign is important)
    * Multiply this "delta" by the scale factor
    * Add the result back to x to get the new x-position of the node
    * Repeat for y
    Very much appreciated. This was my first inclination but I made errors in other places and assumed my approach was incorrect.
    Well now it works wonderfully! The zoom effect is perfect. Now there's just one little hick-up. If I zoom out so far that the nodes actually disappear
    when I zoom back in and they reappear they are all occupying the same exact position and hence, are overlapping.
    Java Code:
    public void mouseWheelMoved(MouseWheelEvent e)
    {
        double oldZoomPercent = Math.max(1, zoomPercent);
        int notches = -e.getWheelRotation();
        int increment = 50;
        zoomPercent += increment * notches;
        zoomPercent = Math.max(0, zoomPercent);
    
        //mouse position
        int x = e.getX();
        int y = e.getY();
    
        for (Node node: nodes)
        {
            int newWidth = (int) (node.defaultWidth * zoomPercent / 100);
            int newHeight = (int) (node.defaultHeight * zoomPercent / 100);
            node.setSize(newWidth, newHeight);
    
            int nodeX = node.getLocation().x;
            int nodeY = node.getLocation().y;
    
            int dx = (int) ((nodeX - x) * zoomPercent / oldZoomPercent);
            int dy = (int) ((nodeY - y) * zoomPercent / oldZoomPercent);
    
            node.setLocation(x + dx, y + dy);
        }
        validate();
    }
    edit: dx seems to get stuck at 0 once the nodes disappear. When they reappear dx is still at 0...
    Last edited by robbie.26; 06-21-2011 at 03:42 AM.

  4. #4
    DarrylBurke's Avatar
    DarrylBurke is offline Member
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,234
    Rep Power
    19

    Default

    Looks like the usual integer math 'problem'. I think you'll have to maintain a pair of double variables for the 'last computed location' of the node. I would also declare dx and dy as double, and cast the final incremented value in setLocation.
    Java Code:
     // x, dx, y, dy are of type double
    // x and y are retained, possibly as custom fields of 'node'
    x += dx;
    y += dy;
    node.setLocation((int) x, (int) y);
    db

Similar Threads

  1. Problem with determing mouse position!!!
    By G.rocks in forum New To Java
    Replies: 6
    Last Post: 07-15-2010, 05:09 PM
  2. repositioning
    By ashish9590 in forum NetBeans
    Replies: 2
    Last Post: 02-14-2010, 06:42 AM
  3. get position in string from caret position
    By helloworld111 in forum AWT / Swing
    Replies: 5
    Last Post: 02-19-2009, 01:36 AM
  4. Replies: 0
    Last Post: 06-25-2008, 10:32 AM
  5. Use the mouse position
    By susan in forum Java Applets
    Replies: 1
    Last Post: 07-28-2007, 11:10 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •