Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8620875
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 12, 20262026-06-12T06:41:09+00:00 2026-06-12T06:41:09+00:00

I am trying to make a zoomable map with Swing. The map is a

  • 0

I am trying to make a zoomable map with Swing. The map is a JPanel in a JScrollPane. When zoomed in, the map changes size and paint() paints the elements in a different position. This all works great.

However, the ScrollPane didn’t change the viewport while increasing the image size, so that zooming in always moved the elements I was looking at out of the screen. I tried to solve this with scrollRectToVisible(), but I don’t manage to get the right coordinates for the rectangle, either because I fail at doing the geometry or because I don’t understand Swing all that well.

Here is what I have:

public class MapPanel extends JPanel {
    [...]

public void setZoom(double zoom) {
    // get the current viewport rectangle and its center in the scaled coordinate system
    JViewport vp = (JViewport) this.getParent();
    Rectangle rect = vp.getViewRect(); 
    Point middle = getMiddle(rect); 
    Dimension dim = rect.getSize();

    // zoom in
    scaler.setZoom(zoom);
    setPreferredSize(scaler.transform(dim));    
    this.revalidate();  

// calculate the full size of the scaled coordinate system  
    Dimension fullDim = scaler.transform(dim); 
    // calculate the non-scaled center of the viewport
    Point nMiddle = new Point((int) ((double) (middle.x)/fullDim.width*dim.width),(int) ((double) (middle.y)/fullDim.height*dim.height));

    // this should do the trick, but is always a bit off towards the origin
    scrollRectToVisible(getRectangleAroundPoint(nMiddle)); 

    // the below alternative always zooms in perfectly to the center of the map 
    // scrollRectToVisible(getRectangleAroundPoint(new Point(400,300)));
}

private Rectangle getRectangleAroundPoint(Point p){
    Point newP = scaler.transform(p);
    Dimension d = railMap.getDimension();
    Point corner = new Point(newP.x-d.width/2,newP.y-d.height/2);
    return new Rectangle(corner,d);
}

private Point getMiddle(Rectangle r){
    return new Point(r.x+r.width/2,r.y+r.height/2);
}
}

And here’s the Scaler class (which does nothing very surprising, I think):

public class Scaler {
    private double zoom = 1;

public void setZoom(double zoom) {
    this.zoom = zoom;
}


public Point transform(Point2D p){
    return new Point((int) (p.getX()*zoom), (int) (p.getY()*zoom));
}


public Dimension transform(Dimension d){
    return new Dimension((int) (d.width*zoom), (int) (d.height*zoom));
}

}

Who can tell me where things are going wrong? It seems to me I did a valid calculation of the current center of the map, and with a fixed zoom point it does work…

Edit: so the hard thing here is to create the new viewport rectangle based on the old viewport rectangle.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-12T06:41:11+00:00Added an answer on June 12, 2026 at 6:41 am

    I just did this really quick example, which basically tries to keep the scroll pane center around the middle of the supplied image

    public class TestZooming {
    
        public static void main(String[] args) {
            new TestZooming();
        }
    
        public TestZooming() {
    
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
    
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException classNotFoundException) {
                    } catch (InstantiationException instantiationException) {
                    } catch (IllegalAccessException illegalAccessException) {
                    } catch (UnsupportedLookAndFeelException unsupportedLookAndFeelException) {
                    }
    
                    JFrame frame = new JFrame();
                    frame = new JFrame();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setSize(400, 400);
                    frame.setLocationRelativeTo(null);
                    frame.setLayout(new BorderLayout());
                    final ZoomPane pane = new ZoomPane();
                    frame.add(new JScrollPane(pane));
                    frame.setVisible(true);
    
                    SwingUtilities.invokeLater(new Runnable() {
    
                        @Override
                        public void run() {
                            pane.centerInViewport();
                        }
    
                    });
    
                }
            });
    
        }
    
        protected class ZoomPane extends JPanel {
    
            private Image background;
            private Image scaled;
            private float zoom = 1f;
    
            private Dimension scaledSize;
            private JViewport con;
    
            public ZoomPane() {
    
                try {
                    background = ImageIO.read(new File("..."));
                    scaled = background;
                    scaledSize = new Dimension(background.getWidth(this), background.getHeight(this));
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
    
                InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
                ActionMap am = getActionMap();
    
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, 0), "plus");
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, InputEvent.SHIFT_DOWN_MASK), "plus");
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, 0), "minus");
    
                am.put("plus", new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        setZoom(getZoom() + 0.1f);
                    }
                });
                am.put("minus", new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        setZoom(getZoom() - 0.1f);
                    }
                });
    
                setFocusable(true);
                requestFocusInWindow();
    
            }
    
            @Override
            public void addNotify() {
    
                super.addNotify();
    
            }
    
            public float getZoom() {
                return zoom;
            }
    
            public void setZoom(float value) {
                if (zoom != value) {
                    zoom = value;
    
                    if (zoom < 0) {
                        zoom = 0f;
                    }
    
                    int width = (int) Math.floor(background.getWidth(this) * zoom);
                    int height = (int) Math.floor(background.getHeight(this) * zoom);
                    scaled = background.getScaledInstance(width, height, Image.SCALE_SMOOTH);
                    scaledSize = new Dimension(width, height);
    
                    if (getParent() instanceof JViewport) {
    
                        int centerX = width / 2;
                        int centerY = height / 2;
    
                        JViewport parent = (JViewport) getParent();
                        Rectangle viewRect = parent.getViewRect();
                        viewRect.x = centerX - (viewRect.width / 2);
                        viewRect.y = centerY - (viewRect.height / 2);
                        scrollRectToVisible(viewRect);
                    }
    
                    invalidate();
                    repaint();
    
                }
            }
    
            @Override
            public Dimension getPreferredSize() {
    
                return scaledSize;
    
            }
    
            @Override
            protected void paintComponent(Graphics g) {
    
                super.paintComponent(g);
    
                if (scaled != null) {
    
                    g.drawImage(scaled, 0, 0, this);
    
                }
    
            }
    
            protected void centerInViewport() {
    
                Container container = getParent();
                if (container instanceof JViewport) {
    
                    JViewport port = (JViewport) container;
                    Rectangle viewRect = port.getViewRect();
    
                    int width = getWidth();
                    int height = getHeight();
    
                    viewRect.x = (width - viewRect.width) / 2;
                    viewRect.y = (height - viewRect.height) / 2;
    
                    scrollRectToVisible(viewRect);
    
                }
    
            }
        }
    }
    

    As to why yours doesn’t work, I can’t say, I can’t run the example, but maybe this will at least give you some ideas…

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Ive been trying to make a scrollable/zoomable app and everything has gone great except
Trying to make td elements clickable. Here's my HTML: <td id=A3 class= open-square><a href=/gameplay/A3></a></td>
Trying to make a make generic select control that I can dynamically add elements
I'm trying to make an image zoomable in my windows phone 7 application. (code
Trying to make some small changes to Apache's Velocity engine. Here's what I can
I'm trying make a login window where a user is prompted to enter their
I'm trying make an entity with doctrine that has three associations with other entities
I am trying make long screen to vertical direction. So, I need a screen
I am fairly new to iOS development and trying make a simple app which
Trying to make this jQuery filter that uses .find case-insensitive. For example, when the

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.