0

i've built a program with a JScrollPane this scrollpane includes another JPanel with null Layout and this panel includes a few other JPanels[I'll name them subpanels] (with some painted things and JLabels) those subpanels are positioned in the panel with the setBounds(int,int,int,int) method (and i don't want to change that)

after searching for a good solution for zooming I've found two options - zoom inside of the paint/paintComponent method (sucks because the painted stuff is changed but not the scale of x,y axis and not the with and height of those subpanels -> my mouselisteners doesn't work (at the wrong place)) - zoom with the viewport of the JScrollPane (doesn't work at all (what i found on google etc.))

so i'm looking for a good solution to zoom in and out of my JPanel

here is some code to imagine what i mean

 import java.awt.Color;
 import java.awt.Dimension;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.Point;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 import java.awt.event.MouseWheelEvent;
 import java.awt.event.MouseWheelListener;
 import java.awt.geom.AffineTransform;

 import javax.swing.JFrame;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;


 public class MyAppFrame extends JFrame {

private JScrollPane scroll;
private JPanel nullLayoutPanel;
private JPanel subPanel;
private double zoomFactor;
private double lastScale;
private static Point pressed;

public MyAppFrame(){
    setSize(200, 200);
    setLocation(50, 50);
    zoomFactor = 1.0;
    lastScale = 1.0;

    nullLayoutPanel = new JPanel(){


        //when you try it with the paint method you'll see my problem
        //move the rect by dragging it around then
        //scroll out or in and try to move the rect
        //you'll see that the position of the logical rect doesn't fit with the painted one
        @Override
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            //g2d.translate(nullLayoutPanel.getWidth()/2, nullLayoutPanel.getHeight()/2);
            g2d.scale(zoomFactor, zoomFactor);
            //g2d.translate(-nullLayoutPanel.getWidth()/2, -nullLayoutPanel.getHeight()/2);
            //super.paint(g2d);
            g2d.dispose();
        }

        @Override
        public Dimension getPreferredSize(){
            return new Dimension((int)(nullLayoutPanel.getWidth()*zoomFactor), (int)(nullLayoutPanel.getHeight()*zoomFactor));
        }

    };
    nullLayoutPanel.setPreferredSize(new Dimension(400,400));
    nullLayoutPanel.setLayout(null);
    nullLayoutPanel.addMouseWheelListener(new MouseWheelListener() {

        @Override
        public void mouseWheelMoved(MouseWheelEvent e) {
            if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL){
                if((.1 * e.getWheelRotation()) > 0 && zoomFactor < 2.0){
                    zoomFactor += (.1 * e.getWheelRotation());
                } else if((.1 * e.getWheelRotation()) < 0 && zoomFactor > 0.1){
                    zoomFactor += (.1 * e.getWheelRotation());
                }
                zoomFactor = Math.round(zoomFactor*10.0)/10.0;
                zoom(e.getPoint());
            }
        }
    });


    scroll = new JScrollPane(nullLayoutPanel);
    scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    getContentPane().add(scroll);

    subPanel = new JPanel(){
        @Override
        public void paint(Graphics g){
            g.setColor(Color.BLUE);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());
        }
    };

    subPanel.addMouseListener(new MouseListener() {

        @Override
        public void mouseReleased(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mousePressed(MouseEvent e) {
            pressed = e.getPoint();
        }

        @Override
        public void mouseExited(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseEntered(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseClicked(MouseEvent e) {
            // TODO Auto-generated method stub

        }
    });
    subPanel.addMouseMotionListener(new MouseMotionListener() {

        @Override
        public void mouseMoved(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseDragged(MouseEvent e) {
            Point pPoint;
            pPoint = subPanel.getLocation();
            int x = (int)(pPoint.x - pressed.getX()+e.getX());
            int y = (int)(pPoint.y - pressed.getY()+e.getY());
            if(x>0&&y>0)
                subPanel.setLocation(x,y);
            repaint();
        }
    });

    subPanel.setBounds(10, 10, 10, 10);
    nullLayoutPanel.add(subPanel);


    setVisible(true);

}

public void alignViewPort(Point mousePosition) {
    // if the scale didn't change there is nothing we should do
    if (zoomFactor != lastScale) {
        // compute the factor by that the image zoom has changed
        double scaleChange = zoomFactor / lastScale;

        // compute the scaled mouse position
        Point scaledMousePosition = new Point(
                (int)Math.round(mousePosition.x * scaleChange),
                (int)Math.round(mousePosition.y * scaleChange)
        );

        // retrieve the current viewport position
        Point viewportPosition = scroll.getViewport().getViewPosition();

        // compute the new viewport position
        Point newViewportPosition = new Point(
                viewportPosition.x + scaledMousePosition.x - mousePosition.x,
                viewportPosition.y + scaledMousePosition.y - mousePosition.y
        );

        // update the viewport position
        // IMPORTANT: This call doesn't always update the viewport position. If the call is made twice
        // it works correctly. However the screen still "flickers".
        scroll.getViewport().setViewPosition(newViewportPosition);

        // debug
        if (!newViewportPosition.equals(scroll.getViewport().getViewPosition())) {
            System.out.println("Error: " + newViewportPosition + " != " + scroll.getViewport().getViewPosition());
        }

        // remember the last scale
        lastScale = zoomFactor;
    }
}

public void zoom(Point p){
    alignViewPort(p);
    nullLayoutPanel.revalidate();
    scroll.repaint();
}

/**
 * @param args
 */
public static void main(String[] args) {
    new MyAppFrame();
}

 }

I hope you understand my problem...

edit: changed some code (viewport things)

DaMp
  • 1
  • 1
  • Did you search the site? There are several answers such as [this](http://stackoverflow.com/questions/6543453/zooming-in-and-zooming-out-within-a-panel). – user1803551 Sep 19 '14 at 14:09
  • I've got the same problem with that code... the painted rect has changed it scale but the logic rect (with the mouselistener) has not changed it's scale only it's position but in a wired way... – DaMp Sep 22 '14 at 09:47
  • How about [this](http://stackoverflow.com/questions/22649636/zoomable-jscrollpane-setviewposition-fails-to-update)? – user1803551 Sep 22 '14 at 11:28
  • And by the way, instead of using `MouseListener` you can use `MouseAdapter` so that you don't need to implement all the methods. – user1803551 Sep 22 '14 at 11:30
  • so I changed some things... now the scrollpane changes in a wired way but my drawed rect stays at the same size... when i zoom out i would like that my drawed rect will be scaled too... – DaMp Sep 23 '14 at 07:54
  • Do you want to zoom on the current mouse location? – user1803551 Sep 23 '14 at 08:21
  • Apparently JXLayer suits this, MadProgrammer made it available [here](https://www.dropbox.com/s/re1hmvypp19oqy1/JXLayer-PBJar-Demo.zip). – user1803551 Sep 23 '14 at 11:02

0 Answers0