2017-09-10 7 views
1

Je veux agrandir l'image lorsque la souris gauche est clic et à l'extérieur lorsque le clic droit de la souris, c'est la partie facile. La partie de l'image après le zoom que je veux montrer est l'endroit où se trouve la souris. Par exemple une image de voiture et ma position de la souris est sur la roue de voiture l'image devrait zoomer mais la mise au point devrait rester sur la voiture. C'est ce qui est fatigué jusqu'ici.Zoom image in and out change également JscrollPane accroding à la position de la souris

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

} 

Merci d'avance.

+0

ne serait-ce rien que l'élaboration de la géométrie sur le papier? –

+0

[Cet exemple] (https://stackoverflow.com/questions/12719085/how-to-zoom-in-to-jpanel-without-moving-the-center-math-or-swing/12719389#12719389) est légèrement différent, en ce sens qu'il s'échelonne autour du centre de la zone visible actuelle, mais pourrait vous donner quelques idées. Peut-être que [cet exemple] (https://stackoverflow.com/questions/15699916/how-do-i-make-this-panel-zoom-toward-the-middle-of-the-panel/15700496#15700496) pourrait aider – MadProgrammer

+1

L'idée générale est que, lorsque vous mettez à l'échelle l'image, vous devez appliquer un décalage de la moitié de la taille résultante à l'emplacement de l'image, qui, en théorie, doit évoluer autour de la zone visible visible. Vous devrez également prendre en considération le décalage de la zone visible et le pointeur de la souris et faire des ajustements à cela aussi bien – MadProgrammer

Répondre

0

je ne pas utiliser le ScrollPane. Voici ma 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(); 
    }` 

Où point.x est et point.y est la position de la souris. Vérifiez également la méthode de traduction des graphiques.

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

+0

Il résout le problème mais ne répond pas à la question que vous avez postée ("changer l'accrochage de JscrollPane à la position de la souris") – c0der

2

Pour zoomer et changer JScrollPane position I a changé deux méthodes et a ajouté 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

Merci le premier clic est me donner une position tout à fait juste, mais le clic suivant la position est l'image n'est pas bonne , Je vérifie le problème. Merci pour le soutien, vous attendra également si vous trouvez plus sur le deuxième clic. –

+0

Oui, je sais. D'où le commentaire: "le calcul n'est pas précis, il faut le perfectionner". Je n'ai pas eu le temps de le vérifier en profondeur. Je voulais juste démontrer les bases et vous donner un début. Postez une amélioration quand vous l'avez. – c0der

+0

Je l'ai compris, nous n'avons pas besoin de tout type de calcul int moveX = point.x; \t int moveY = point.y; –