3

I have problem with displaying the image on JPanel when I rescaled the image according to the size of the JPanel. The image did not appear.

   public class createGUII extends JFrame{
        String [] background = {"c1.jpg","c2.jpg","c3.jpg","c4.jpg"};                       
        ArrayList<String> bgPicturesFiles   = new ArrayList<String>(Arrays.asList(background)); 


    JPanel panel;
    ImagePanel imgBg;

    public createGUII(){
        GridBagLayout m = new GridBagLayout();
        Container c = getContentPane();
        c.setLayout (m);
        GridBagConstraints con = new GridBagConstraints();

       //Panel for background
        panel = new JPanel();       
        panel.setSize(600, 600);
        con = new GridBagConstraints();
        con.anchor=GridBagConstraints.CENTER;
        con.gridy = 1;      con.gridx = 0;
        con.gridwidth = 1;  con.gridheight = 1;     
        m.setConstraints(panel, con);   
        c.add(panel);

       //randomized the image files
        Random r = new Random();                        
        int random = r.nextInt(bgPicturesFiles.size());

       //rescale the image according to the size of the JPanel 
        imgBg = new ImagePanel(new ImageIcon(bgPicturesFiles.get(random)).getImage().getScaledInstance(panel.getHeight(), panel.getWidth(),Image.SCALE_SMOOTH));            
        panel.add(imgBg);

        setResizable(false);
        setVisible(true);       
        setExtendedState(getExtendedState()|JFrame.MAXIMIZED_BOTH);             

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new createGUII();       
            }
        });
    }
}



class ImagePanel extends JPanel {
    private Image img;

    public ImagePanel(String img) {
        this(new ImageIcon(img).getImage());
    }

    public ImagePanel(Image img) {
        this.img = img;
        Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
        setPreferredSize(size);
        setMinimumSize(size);
        setMaximumSize(size);
        setSize(size);
        setLayout(null);
        }

    public void paintComponent(Graphics g) {
        g.drawImage(img, 0, 0, null);
        }
}     
Jessy
  • 15,321
  • 31
  • 83
  • 100

4 Answers4

1

Have a look at this: JPanel background image, JPanel with background image, with other panels overlayed

The second link mentions that you have to do some custom painting for scaling. This is a problem. I wouldn't scale the image every single time in the paintComponent method, but do it once if the width and height have been changed since the last call, and in that case, recreate a BufferedImage containing the image which you blit every single time before calling the superclass paintComponent, scaled up to the right size (use something like Image scaling does not work when original image height & width is smaller the scaling height & width). I can see an issue where it might try to fill the panel with a colour when you call the superclass paintComponent method, but you'll have to experiment.

Community
  • 1
  • 1
Chris Dennett
  • 22,412
  • 8
  • 58
  • 84
0

I don't see where you're actually reading the image, as suggested in this example.

Addendum: I've added an example of scaling. See also Don't Use getScaledInstance() and The Perils of Image.getScaledInstance().

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/** @see http://stackoverflow.com/questions/4170463 */
public class LoadImage extends JPanel {

    private Image image;

    public LoadImage() {
        super(new GridLayout());
        try {
            image = ImageIO.read(new File("image.jpg"));
        } catch (IOException ex) {
            ex.printStackTrace(System.err);
        }
        int w = image.getWidth(null) / 2;
        int h = image.getHeight(null) / 2;
        this.add(new JLabel(new ImageIcon(
            image.getScaledInstance(w, h, Image.SCALE_SMOOTH))));
    }

    private void display() {
        JFrame f = new JFrame("LoadImage");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new LoadImage().display();
            }
        });
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Isn't the image being read and created in the ImagePanel constructor via ImageIcon? Seems a bit messy but it probably works. – Chris Dennett Nov 13 '10 at 03:22
  • I think the title maybe wrong. Actually what I want to do is rescaling the image. If I did not rescale the image, the image appeared on screen, but when I rescale it, it doesn't appear. – Jessy Nov 13 '10 at 03:23
  • The image appeared if I just use this code .. imgBg = new ImagePanel(new ImageIcon(bgPicturesFiles.get(random)).getImage()); – Jessy Nov 13 '10 at 03:25
  • @Jessy: I added scaling to my example, but I'm not sure why your code fails. – trashgod Nov 13 '10 at 04:29
0

The problem is that in Java images get loaded asynchronously. There are several issues with the above code because of that:

  • The image doesn't get loaded, so it's dimensions are (-1, -1). Thus, ImagePanel's size is invalid
  • Even if the dimensions get set manually (i.e. changing it to new Dimension(600, 600)), the image itself may not be loaded.
  • JFrame resizing is disabled. If you allow it, you would be able to get the image drawn with the above code by artificially making Swing load the image when the JFrame is resized

To ensure loading, add the following:

new ImageIcon(img).getImage();

after this.img = img; in ImagePanel's constructor.

Note that this is partially a hack - I'm not a GUI expert, but I get the idea the above could be written much better. Maybe somebody else might be able to shed more light.

Here are some links that might be helpful:

Hope this helps.

icyrock.com
  • 27,952
  • 4
  • 66
  • 85
0

Here is a link that should help. However I found a way that better suited the problem I had this was what I found, and the following is what I took from that.

I hope this helps.

Container con = getContentPane();
final String backgroundPath = "C:\\background.jpg";

ImageIcon imh = new ImageIcon(backgroundPath);
setSize(imh.getIconWidth(), imh.getIconHeight());

JPanel pnlBackground = new JPanel()
{
    public void paintComponent(Graphics g) 
    {
        Image img = new ImageIcon(backgroundPath).getImage();
        g.drawImage(img, 0, 0, null);
    }
};

con.add(pnlBackground);
pnlBackground.setBounds(0, 0, imh.getIconWidth(), imh.getIconHeight());
thewikus
  • 445
  • 1
  • 5
  • 16