Zoom image in and out also change JscrollPane according to mouse position

半腔热情 提交于 2019-12-11 02:51:12

问题


I want to zoom image in when left mouse is click and out when right mouse is click, This is the easy part. The portion of image after zoom I want to show is where the mouse is.

e.g an image of car and my mouse position is on car wheel the image should zoom but the focus should remain on car. That's what is tired so far.

package paractice;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class Zoom extends JPanel implements ActionListener, MouseListener, MouseMotionListener{

    private static final long serialVersionUID = 1L;
    private JLabel imageAdujuster = new JLabel();
    private JPanel panel = new JPanel();
    private JScrollPane pane = new JScrollPane();
    private JButton zoomIn = new JButton("Zoom IN");
    private JButton zoomOut = new JButton("Zoom Out");
    private Point point;
    private BufferedImage image;
    private double scale = 1;

    /*
     * Constructor
     */
    public Zoom() {

        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        buttonPanel.add(zoomOut);
        buttonPanel.add(zoomIn);

        panel.setLayout(new BorderLayout());
        panel.add(imageAdujuster, BorderLayout.CENTER);
        pane.setViewportView(panel);
        pane.setAutoscrolls(true);


        setLayout(new BorderLayout());
        add(pane, BorderLayout.CENTER);
        add(buttonPanel, BorderLayout.SOUTH);

        zoomOut.addActionListener(this);
        zoomIn.addActionListener(this);

        imageAdujuster.addMouseListener(this);
        imageAdujuster.addMouseMotionListener(this);

    }

    private void getImage(String imagePath){
        try {
            File imageFile = new File(imagePath);
            image = ImageIO.read(imageFile);
            setImage(image);
        }catch(Exception e){
            System.out.println("Image file not found. "+ e.getMessage());
        }
    }

    private void setImage(Image image) {
        imageAdujuster.setIcon(new ImageIcon(image));
    }

    private BufferedImage getScaledImage(double scale) {  
        int w = (int)(scale*image.getWidth());  
        int h = (int)(scale*image.getHeight());  
        BufferedImage bi = new BufferedImage(w, h, image.getType());  
        Graphics2D g2 = bi.createGraphics();  
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,  
                            RenderingHints.VALUE_INTERPOLATION_BICUBIC);  
        AffineTransform at = AffineTransform.getScaleInstance(scale, scale);  
        g2.drawRenderedImage(image, at);  
        g2.dispose();  
        return bi;  
    }

    public void zoomOut(Point point) {
        setImage(getScaledImage(scale * 0.9));
        Point pos = pane.getViewport().getViewPosition();

        int newX = (int)(point.x*(0.9f - 1f) + 0.9f*pos.x);
        int newY = (int)(point.y*(0.9f - 1f) + 0.9f*pos.y);
        pane.getViewport().setViewPosition(new Point(newX, newY));

        this.pane.revalidate();
        this.pane.repaint();
    }

    /**
     * 
     */
    public void zoomIn(Point point) {
        setImage(getScaledImage(scale * 1.1f));
        Point pos = pane.getViewport().getViewPosition();

        int newX = (int)(point.x*(1.1f - 1f) + 1.1f*pos.x);
        int newY = (int)(point.y*(1.1f - 1f) + 1.1f*pos.y);
        pane.getViewport().setViewPosition(new Point(newX, newY));

        this.pane.revalidate();
        this.pane.repaint();
    }

    public static void main(String args[]) {
        JFrame frame  = new JFrame();

        Zoom zoom = new Zoom();
        zoom.getImage("C:\\Users\\abcd1\\Pictures\\picture.jpg");

        frame.getContentPane().add(zoom);
        frame.pack();
        frame.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {

        if(e.getSource() == zoomIn) {
            scale ++;
            zoomIn(point);
        }

        if(e.getSource() == zoomOut) {
            scale --;
            zoomOut(point);
        }


    }

    public void mouseClicked(MouseEvent e) {
        if(SwingUtilities.isLeftMouseButton(e)) {
            scale += 1;
            zoomIn(point);
        }

        if(SwingUtilities.isRightMouseButton(e)) {
            scale -= 1;
            zoomOut(point);
        }
    }

    public void mouseMoved(MouseEvent e) {
        PointerInfo info = MouseInfo.getPointerInfo();
        point = info.getLocation();

        System.out.println("point x is "+point.x +" point y is "+point.y);

    }

    public void mouseEntered(MouseEvent arg0) {}

    public void mouseExited(MouseEvent arg0) {}

    public void mousePressed(MouseEvent arg0) {}

    public void mouseReleased(MouseEvent arg0) {}

    public void mouseDragged(MouseEvent e) {}
}

回答1:


To zoom and change JScrollPane position I changed two methods and added scaleAndZoom(double) :

public void zoomOut(Point point) {

    scaleAndZoom( scale * 0.9f);
}

public void zoomIn(Point point) {

    scaleAndZoom( scale * 1.1f);
}

private void scaleAndZoom(double scale) {

    setImage(getScaledImage(scale));

    //calculation is not quiet accurate. Need to improve 
    //see Aqeel Haider comment 
    int moveX = (int) ((scale* point.x) - point.x ) ;
    int moveY = (int) ((scale* point.y) - point.y ) ;

    Rectangle view = pane.getViewport().getViewRect();
    view.setBounds(view.x+moveX,view.y+moveY, view.width, view.height);

    imageAdujuster.scrollRectToVisible(view);
}



回答2:


I didn't use the ScrollPane. Here my Solution.

public void paint(Graphics g) {
         Graphics2D g2d = (Graphics2D)g;
            int w = this.getWidth();
            int h = this.getHeight();
            if(orginalImage == null )return;

            int imageWidth = orginalImage.getWidth();
            int imageHeight = orginalImage.getHeight();
            BufferedImage bi = new BufferedImage(
                    (int)(imageWidth*scale), 
                    (int)(imageHeight*scale), 
                    orginalImage.getType());

            Graphics2D g2 = bi.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);

            g2d.translate(point.x, point.y);
            g2d.scale(scale, scale);
            g2d.translate(-point.x, -point.y);
            //g2d.translate(-w/2, -h/2);
            g2d.drawImage(orginalImage, 0, 0, w, h, null);

            this.setPreferredSize(new Dimension(orginalImage.getWidth(), orginalImage.getHeight()));
            if(selection == null) return;

            g2d.setStroke(new BasicStroke(2));
            g2d.setColor(Color.RED);
            g2d.draw(selection);

            resizeImage();
     }`

Where point.x is and point.y is the mouse position. also check translate method of the Graphics.

https://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html#translate(int,%20int)



来源:https://stackoverflow.com/questions/46144737/zoom-image-in-and-out-also-change-jscrollpane-according-to-mouse-position

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!