1

I am trying to create a JPanel with a background image inside another JPanel but the background image is not showing up. How do I fix this?

public class CustomPanel extends JPanel{
     Image img;
     private final static String BACKGROUND = "images/background.png";

     private void loadImage(String filename){
         try{
             img = Toolkit.getDefaultToolkit().getImage(filename);
         } catch(Exception e){}
     }

     @Override
     public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(this.img, 0, 0,null);//display this image as a background
    Toolkit.getDefaultToolkit().sync();//makes animations smooth
     }

     public CustomPanel(){
         this.setLayout(null);
         this.loadImage(this.BACKGROUND);//prepare background image
         this.repaint();//set bg image


}

}

This is the MainPanel which will hold other JPanels with background.

public class MainPanel extends JPanel{
public Container container;
    public MainPanel(Container container){
         this.setLayout(null);
         this.container = container;
         CustomPanel panel= new CustomPanel();
         this.add(panel);
     }
 }

I have read other questions related to this and most of it are failure to set super.paintComponent(g). I have done this in my code so I don't really know what seems to be the problem

Vince
  • 11
  • 1
  • 1
    Do you successfully get the image in the `img` variable ? Also avoid catching an `Exception` silently, or you will never know what might have crashed . – Arnaud May 19 '17 at 13:22
  • 1
    1) *"JPanel with a background image inside another JPanel"* This problem is partly caused by `this.setLayout(null);` in the 'other' panel. Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). 2) For better help sooner, post a [MCVE]. – Andrew Thompson May 19 '17 at 13:37
  • Thanks for your suggestion! – Vince May 19 '17 at 13:46
  • *"Thanks for your suggestion!"* Who are you replying to? Tip: Add @Berger (or whoever, the `@` is important) to *notify* the person of a new comment. – Andrew Thompson May 19 '17 at 14:00

2 Answers2

1

By default components have a size of (0, 0) so there is nothing to paint.

You need to override the getPreferredSize() method of your CustomPanel to return the size of the image.

Then the layout manager can use this information the to set the size and location of the panel.

However, since you are just painting the image at its actual size, then another solution is to just add an ImageIcon to a JLabel and add the label to the panel. Custom painting is only necessary if you plan to alter the image, maybe by scaling it to fit the size of the panel as it changes.

See Background Panel for more information and examples.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • *"Then the layout manager can use this information the to set the size and location of the panel."* The outer panel has this line: `this.setLayout(null);` .. – Andrew Thompson May 19 '17 at 15:06
  • @AndrewThompson, yes, you already told him not to use a null layout and to use a layout manager. That suggestion on its own will not solve the problem so I just added more information. – camickr May 19 '17 at 15:43
  • *"That suggestion on its own will not solve the problem"* It would if the outer panel had a `BorderLayout` or `GridLayout` (and the OP uses `setSize(..)` on the top level container rather than `pack()`). But more seriously, answers should not rely on comments as 'extra information'. They should be self contained. – Andrew Thompson May 19 '17 at 16:17
  • @AndrewThompson, I know the answer didn't explicitly tell the OP not to use a null layout, but it did tell the OP that if you use a layout manager and override getPreferredSize() it will work (regardless of the layout manager being used. I wasn't really relying on the comment (since I did mention the layout manager in my answer) but the fact that a layout manager was mentioned twice should be enough for the OP to understand the problem and solution. – camickr May 19 '17 at 18:14
0

Two things could be wrong that I can see :

  1. Exception being thrown in Toolkit.getDefaultToolkit().getImage(filename). So as @Berger mentionned, I would print out the exception;
  2. MainPanel container not properly set, we do not see that part of the code so I would verify it.

To see a working example see How do I draw an image to a JPanel or JFrame?

Community
  • 1
  • 1
Demogorii
  • 656
  • 5
  • 16
  • 1
    [`Toolkit#getImage`](https://docs.oracle.com/javase/8/docs/api/java/awt/Toolkit.html#getImage-java.lang.String-) doesn't throw an exception (throws an error), this is one of the reaons `ImageIO.read` is generally recommended, because it will throw an exception rather the failing silently – MadProgrammer May 19 '17 at 22:27