Search code examples
javaimageswingjscrollpane

Making image scrollable in JFrame contentpane


I am trying to display a large image inside a JFrame's contentpane. I would like to make the image or contentpane scrollable as the image is large. I tried to do it using Jscrollpane and add it into the contentpane but it didn't work. Did some searching for solution but end up failed to find one. Can someone guide me? My code are below

FinalEnvironment.java

package environment;

import java.awt.*;
import java.net.URL;

import javax.swing.*;

public class FinalEnvironment{

public FinalEnvironment(){

    Image Eastlake;
    URL EastlakeURL = null;

    EastlakeURL = FinalEnvironment.class.getResource("/image1/eastlake_night.png");
    Eastlake = Toolkit.getDefaultToolkit().getImage(EastlakeURL);

    JFrame frame = new JFrame("UniCat World");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(800, 600);
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);

    JMenuBar yellowMenuBar = new JMenuBar();
    Map map = new Map(800, 550, Eastlake);
    yellowMenuBar.setOpaque(true);
    yellowMenuBar.setBackground(Color.YELLOW);
    yellowMenuBar.setPreferredSize(new Dimension(800, 50));
    frame.setJMenuBar(yellowMenuBar);
    JScrollPane scroller = new JScrollPane(map);
    scroller.setAutoscrolls(true);
    scroller.setPreferredSize(new Dimension(800, 550));
    frame.getContentPane().add(scroller, BorderLayout.CENTER);


    frame.setSize(800, 600);
    frame.setVisible(true);
}

public static void main(String[] args){
    FinalEnvironment fe = new FinalEnvironment();
}
}

Here is my map.java

package environment;

import java.awt.*;

import javax.swing.*;


public class Map extends JPanel{

    private int width;
    private int height;
    private Image img;

    public Map(int width, int height, Image img){

        this.width = width;
        this.height = height;
        this.img = img;
    }

    protected void  paintComponent(Graphics g)
    {
        super.paintComponents(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(img,0,0,2624,1696,null);
    }

}

Lastly, I would like to place Jbuttons on top of this image. Should I call a Rectangle and place it on top the image in the contentpane which then I use Point to position my buttons or should I straight away use the image or the component itself to do it? I need the button to be able to synchronize with the image when it is scrolled instead of static in the contentpane.

Thanks


Solution

  • What I would do here:

    1.Have a panel (canvas) which only responsibility is to paint a given image independent of the real image size in overridden method paintComponent()

        super.paintComponent(g);
        g.drawImage(image, 0, 0, null);
    

    2.Make sure the canvas preferred size equals to image real size.

    3.Have a second panel which will serve as content pane of a frame.

    4.In it you will set a JScrollPane as its centre.

    5.In the scroll pane viewport will be the component from step 1.

    6.Add your button to canvas panel from step 1. It will be scrolled together with the image.

    7.Add the content pane, the panel from step 3, to a frame, and run the application.

    EDIT: Code sample with button added to canvas, which stays always in its place, independent of scroll position or frame size.

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.URL;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.imageio.ImageIO;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.SwingUtilities;
    
    public class ScrollImageTest extends JPanel {
        private static final long serialVersionUID = 1L;
        private BufferedImage image;
        private JPanel canvas;
    
        public ScrollImageTest() {
            try {
                this.image = ImageIO.read(new URL("http://interviewpenguin.com/wp-content/uploads/2011/06/java-programmers-brain.jpg"));
            }catch(IOException ex) {
                Logger.getLogger(ScrollImageTest.class.getName()).log(Level.SEVERE, null, ex);
            }
    
            this.canvas = new JPanel() {
                private static final long serialVersionUID = 1L;
                @Override
                protected void paintComponent(Graphics g) {
                    super.paintComponent(g);
                    g.drawImage(image, 0, 0, null);
                }
            };
            canvas.add(new JButton("Currently I do nothing"));
            canvas.setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
            JScrollPane sp = new JScrollPane(canvas);
            setLayout(new BorderLayout());
            add(sp, BorderLayout.CENTER);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JPanel p = new ScrollImageTest();
                    JFrame f = new JFrame();
                    f.setContentPane(p);
                    f.setSize(400, 300);
                    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    f.setVisible(true);
                }
            });
        }
    }