【问题标题】:Zoom image in and out also change JscrollPane according to mouse position放大和缩小图像也会根据鼠标位置更改 JscrollPane
【发布时间】:2017-09-10 19:30:23
【问题描述】:

我想在单击鼠标左键时放大图像,在单击鼠标右键时放大图像,这是最简单的部分。我想显示的缩放后的图像部分是鼠标所在的位置。

例如汽车的图像,我的鼠标位置在车轮上,图像应该缩放,但焦点应该保持在汽车上。到此为止就这么累了。

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) {}
}

【问题讨论】:

  • 这不就是在纸上算出几何吗?
  • This example 略有不同,它围绕当前可视区域的中心进行缩放,但可能会给您一些想法。也许this example 可能会有所帮助
  • 一般的想法是,当你缩放图像时,你需要将结果大小的一半的偏移量应用到图像的位置,理论上应该围绕当前可视区域进行缩放。您还需要考虑到可视区域和鼠标指针的偏移,并对其进行调整

标签: java swing jscrollpane


【解决方案1】:

为了缩放和改变JScrollPane的位置,我改变了两种方法并添加了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);
}

【讨论】:

  • 谢谢第一次点击给了我相当正确的位置,但是下一次点击位置是图像不正确,我正在检查问题。感谢您的支持,如果您有更多关于第二次点击的信息,也会等待。
  • 是的,我知道。因此评论:“计算并不准确。需要改进”。我没有时间深入检查它。只是想展示基础知识并给你一个开始。有改进后发布。
  • 我明白了,我们根本不需要任何计算 int moveX = point.x ; int moveY = point.y ;
【解决方案2】:

我没有使用 ScrollPane。这是我的解决方案。

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();
     }`

point.x 是,point.y 是鼠标位置。还要检查图形的翻译方法。

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

【讨论】:

  • 它解决了问题,但没有回答您发布的问题(“更改 JscrollPane 符合鼠标位置”)
猜你喜欢
  • 2013-02-04
  • 2012-10-20
  • 1970-01-01
  • 2016-09-12
  • 2014-05-23
  • 2020-09-07
  • 1970-01-01
  • 2020-02-01
  • 2013-10-07
相关资源
最近更新 更多