-1

Hi guys I have a problem with Images drawn in a JPanel.There is no problem when the images are drawn to the panel. The Problemm occurn when I scroll up or down the image. The part of the image that was not seen in the viewport is painted white when return to that part again.

I added a BufferedImage in a JPanel. I can also resize the image using AffineTransform. The problem is when I added a JScollPane to my image, whenever I scroll up or down the scrollpane some part of the image disappears ..

I also tried using drawRenderedImage it did solve the problem about the scroll but it messed up other functions.

this is the best concise code I can make;

package convert;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;

public class ZoomTest {

    public static void main(String[] args) {
        ImagePanel panel = new ImagePanel();

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        f.getContentPane().add(new JScrollPane(panel));
        f.setSize(1200, 1200);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class ImagePanel extends JPanel {

    BufferedImage image;
    double scale;

    public ImagePanel() {
        loadImage();
        scale = .38;
        addMouseWheelListener(new MouseWheelListener() {

            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                int rotation = e.getWheelRotation();
                if (rotation < 0) {
                    scale -= .05;
                } else {
                    scale += .05;
                }
                if (scale < 0) {
                    scale = 0;
                }

                revalidate();
                repaint();

            }
        });

    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;

        double x = (getWidth() - scale * image.getWidth()) / 2;
        double y = (getHeight() - scale * image.getHeight()) / 2;

        AffineTransform at = new AffineTransform();
        at.translate(x, y);

        at.scale(scale, scale);
        g2.setTransform(at);

        g2.drawImage(image, 0, 0, null);

    }

    public Dimension getPreferredSize() {
        int w = (int) (scale * image.getWidth());
        int h = (int) (scale * image.getHeight());
        return new Dimension(w, h);
    }

    private void loadImage() {
        String fileName = "c:\\users\\john ebarita\\downloads\\lorem-ipsum-1.jpg";
        try {
            image = ImageIO.read(new File(fileName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
John
  • 45
  • 8
  • Start by using `Graphics2D g2 = (Graphics2D) g.create();` instead of `Graphics2D g2 = (Graphics2D) g;` add `g2.dispose()` at the end of the `paintComponent` method – MadProgrammer Aug 01 '19 at 06:45
  • Sorry about that, but I already did that but still no luck. – John Aug 01 '19 at 06:47
  • This is possibly an issue with the way `JScrollPane` works. I would consider stating by scaling the image outside of the `paintComponent` method (into a "scaled" variable) and simply paint the scaled version instead – MadProgrammer Aug 01 '19 at 07:19
  • Are you able to reproduce the scenario? – John Aug 01 '19 at 07:34
  • Yes and JScrollPane is heavily optimised, it takes small “snapshots” of the component and simply appends then as required, so doing the scaling inside the paintComponent method May screwing with this blitting process – MadProgrammer Aug 01 '19 at 07:57
  • 1) Aside: `g2.drawImage(image, 0, 0, null);` should be `g2.drawImage(image, 0, 0, this);` 2) *"Maybe some code would help."* Speaking about helpful code, I saw `String fileName = "c:\\users\\john ebarita\\downloads\\lorem-ipsum-1.jpg";`. One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). E.G. [This answer](https://stackoverflow.com/a/10862262/418556) hot links to an image embedded in [this question](https://stackoverflow.com/q/10861852/418556). – Andrew Thompson Aug 01 '19 at 08:21

2 Answers2

1

Here is solution for your problem. I had also a bad luck with custom painting, so my solution is directly update the image on mouse wheel and set it to a label.

import java.awt.Image;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;

public class ZoomTest {

    public static void main(String[] args) {
        ImagePanel panel = new ImagePanel();

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        f.getContentPane().add(new JScrollPane(panel));
        f.setSize(1000, 1000);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class ImagePanel extends JLabel {

    BufferedImage image;

    double scale;

    public ImagePanel() {
        setHorizontalAlignment(SwingConstants.CENTER);
        loadImage();
        scale = .38;
        updateImage();
        addMouseWheelListener(new MouseWheelListener() {

            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                int rotation = e.getWheelRotation();
                if (rotation < 0) {
                    scale -= .05;
                } else {
                    scale += .05;
                }
                if (scale < 0) {
                    scale = 0;
                }
                updateImage();
                revalidate();
                repaint();

            }
        });

    }

    private void updateImage() {
        int w = (int) (scale * image.getWidth());
        int h = (int) (scale * image.getHeight());
        setIcon(new ImageIcon(image.getScaledInstance(w, h, Image.SCALE_SMOOTH)));
    }

    private void loadImage() {
        String fileName = "c:\\users\\john ebarita\\downloads\\lorem-ipsum-1.jpg";
        try {
            image = ImageIO.read(new File(fileName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Sergiy Medvynskyy
  • 11,160
  • 1
  • 32
  • 48
1

Take a look at Graphics2D#drawImage(Image, AffineTransform, ImageObserver). May be it helps.

package convert;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;

public class ZoomTest2 {
  public static void main(String[] args) {
    ImagePanel panel = new ImagePanel();
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.getContentPane().add(new JScrollPane(panel));
    f.setSize(1200, 1200);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

class ImagePanel extends JPanel {
  BufferedImage image;
  double scale;

  public ImagePanel() {
    loadImage();
    scale = .38;
    addMouseWheelListener(new MouseWheelListener() {
      @Override
      public void mouseWheelMoved(MouseWheelEvent e) {
        int rotation = e.getWheelRotation();
        if (rotation < 0) {
          scale -= .05;
        } else {
          scale += .05;
        }
        if (scale < 0) {
          scale = 0;
        }
        revalidate();
        repaint();
      }
    });
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g.create();

    double x = (getWidth() - scale * image.getWidth()) / 2;
    double y = (getHeight() - scale * image.getHeight()) / 2;
    AffineTransform at = new AffineTransform();
    at.translate(x, y);
    at.scale(scale, scale);

    // g2.setTransform(at);
    // g2.drawImage(image, 0, 0, this);
    g2.drawImage(image, at, this);

    // or:
    // AffineTransform atf = g2.getTransform();
    // atf.concatenate(at);
    // g2.setTransform(atf);
    // g2.drawImage(image, 0, 0, this);

    g2.dispose();
  }

  public Dimension getPreferredSize() {
    int w = (int)(scale * image.getWidth());
    int h = (int)(scale * image.getHeight());
    return new Dimension(w, h);
  }

  private void loadImage() {
    String fileName = "aaa.png";
    try {
      image = ImageIO.read(new File(fileName));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
aterai
  • 9,658
  • 4
  • 35
  • 44