Image Pan and Zooming

3.1k views Asked by At

I want to display an image to zoom in and out and can be shifted. I have the script below, but it can not be shifted. how to fix it.

the code :

package dispertasih;

import static dispertasih.PanPanel.startX;
import java.awt.*;  
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.*;  
import java.awt.image.BufferedImage;  
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.*;  
import javax.swing.event.*;  

public class PadAndZoom implements ChangeListener {  
    BufferedImage image;  
    PanPanel label;  

    public void stateChanged(ChangeEvent e) {  
        int value = ((JSlider)e.getSource()).getValue();  
        double scale = value/200.0;  
        BufferedImage scaled = getScaledImage(scale);  
       label = new PanPanel(scaled);  
        label.revalidate();  // signal scrollpane  
    }  

    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;  
    }  

    private PanPanel getContent() {  
        createAnImage();  
        label = new PanPanel(image);  
        //label.setHorizontalAlignment(JLabel.CENTER);  
        return label;  
    }  

    private void createAnImage() {  
        int w = 500;  
        int h = 500;  
        int type = BufferedImage.TYPE_INT_RGB; // many options  
        try {
            image = ImageIO.read(PadAndZoom.class.getResource("/tampilan/background5.jpg"));
        } catch (IOException ex) {
            Logger.getLogger(PadAndZoom.class.getName()).log(Level.SEVERE, null, ex);
        }


    }  

    private JSlider getControl() {  
        JSlider slider = new JSlider(JSlider.HORIZONTAL, 50, 200, 50);  
        slider.setMajorTickSpacing(50);  
        slider.setMinorTickSpacing(10);  
        slider.setPaintTicks(true);  
        slider.setPaintLabels(true);  
        slider.addChangeListener(this);  
        return slider;          
    }  

    public static void main(String[] args) {  
        PadAndZoom app = new PadAndZoom();  
        JFrame f = new JFrame();  
        JButton b = new JButton();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
        f.getContentPane().add(new JScrollPane(app.getContent()));  

        //f.getContentPane().add(new JButton("tessss"));
        f.getContentPane().add(app.getControl(), "Last");  
        f.setSize(400, 400);  
        f.setLocation(200,200);  
        f.setVisible(true);  
    }  
}  
class PanPanelX extends JPanel {

private int x, y;
private int width = 800, height = 800;
BufferedImage img;
private final static RenderingHints textRenderHints = new    RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
private final static RenderingHints imageRenderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
private final static RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
static int startX, startY;

public PanPanelX(BufferedImage img) {
    x = 20;
    y = 20;
    this.img = img;

    addMouseListener(new MouseAdapter() {
        @Override
        public void mousePressed(MouseEvent me) {
            super.mousePressed(me);
            startX = me.getX();
            startY = me.getY();
        }
    });

    addMouseMotionListener(new MouseMotionAdapter() {
        @Override
        public void mouseDragged(MouseEvent me) {
            super.mouseDragged(me);

            if (me.getX() < startX) {//moving image to right
                x -= 2;
            } else if (me.getX() > startX) {//moving image to left
                x += 2;
            }

            if (me.getY() < startY) {//moving image up
                y -= 2;
            } else if (me.getY() > startY) {//moving image to down
                y += 2;
            }
            repaint();
        }
    });
}

@Override
protected void paintComponent(Graphics grphcs) {
    super.paintComponent(grphcs);
    Graphics2D g2d = (Graphics2D) grphcs;

    //turn on some nice effects
    applyRenderHints(g2d);

    g2d.drawImage(img, x, y, null);
}

@Override
public Dimension getPreferredSize() {
    return new Dimension(width, height);
}

public static void applyRenderHints(Graphics2D g2d) {
    g2d.setRenderingHints(textRenderHints);
    g2d.setRenderingHints(imageRenderHints);
    g2d.setRenderingHints(renderHints);
}
}

i think on :

public void stateChanged(ChangeEvent e) {  
        int value = ((JSlider)e.getSource()).getValue();  
        double scale = value/200.0;  
        BufferedImage scaled = getScaledImage(scale);  
       label = new PanPanel(scaled);  
        label.revalidate();  // signal scrollpane  
    } 

there are mistakes, but I've stuck fixing it....

thank you ...

1

There are 1 answers

0
MadProgrammer On BEST ANSWER

The problem is, the reference of the image that is displayed on the screen is not the same as the image you are creating when you resize it...

You create PanPanel by using...

BufferedImage scaled = getScaledImage(scale);
label = new PanPanel(scaled);

getScaledImage creates a new image each time it is called, based on the original image.

BufferedImage bi = new BufferedImage(w, h, image.getType());

This means, that the image in PadAndZoom is not the same as the one in PanPanel, so any changes you make to image or any new scaled instances will never be painted because PanPanel knows nothing about them...

Now, in stateChanged, instead of updating the instance of PanPanel that you already have, you create a new instance of it...and that's it...it's never added to any displayable component, so it will never appear on the screen.

Instead, in your PanPanel, you need to supply some way for the stateChanged method to pass the scaled instance of the image to it...

public void setImage(BufferedImage img) {
    this.img = img;
    revalidate();
    repaint();
}

Then in your stateChanged method you can do...

int value = ((JSlider) e.getSource()).getValue();
double scale = value / 200.0;
BufferedImage scaled = getScaledImage(scale);
label.setImage(scaled);