2017-09-10 95 views
1

我想放大图像,当点击鼠标左键时,点击鼠标右键,这是很容易的部分。我想要显示的缩放后的图像部分是鼠标的位置。缩放图像进出也改变JscrollPane accroding到鼠标位置

例如,汽车的图像和我的鼠标位置在车轮上,图像应该放大,但焦点应该保留在汽车上。到目前为止,这是累赘。

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

} 

在此先感谢您。

+0

难道这不是什么,只是在纸上计算出几何图形吗? –

+0

[This example](https://stackoverflow.com/questions/12719085/how-to-zoom-in-to-jpanel-without-moving-the-center-math-or-swing/12719389#12719389)略微不同,因为它围绕当前可视区域的中心缩放,但可能会给你一些想法。也许[这个例子](https://stackoverflow.com/questions/15699916/how-do-i-make-this-panel-zoom-toward-the-middle-of-the-panel/15700496#15700496)可能有帮助 – MadProgrammer

+1

总体思路是,在缩放图像时,需要将所得尺寸的一半偏移量应用于图像的位置,理论上应该在当前可视区域周围进行缩放。你还需要考虑从可视区域和鼠标指针的偏移量,并作出调整以及 – MadProgrammer

回答

0

我没有使用滚动窗格。这里我的解决方案

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)

+0

它解决了问题,但未回答您发布的问题(“将JscrollPane更改为鼠标位置”) – c0der

2

要放大,改变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); 
} 
+0

谢谢第一次点击是给我很正确的位置,但下一次点击的位置是图像不正确,我正在检查问题。感谢您的支持,如果您发现更多关于第二次点击的信息,也将等待。 –

+0

是的,我知道。因此评论:“计算不安静准确,需要改进”。我没有时间深入检查它。只是想展示基础知识并给你一个开始。当你拥有它时发布改进。 – c0der

+0

我弄明白了,我们根本不需要任何计算int moveX = point.x; \t int moveY = point.y; –