0

I am new to making GUIs so I decided to try the the windows builder for eclipse, and while great I do have some doubts. I have been searching but I cannot seen to find a good way to add a background image to my "menu". For example I tried this:

public Menu() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(50, 50, 300, 250); //Dimensiones

contentPane = new JPanel() {  //Imagen de Fondo

    public void paintComponent(Graphics g) {  
          Image img = Toolkit.getDefaultToolkit().getImage(  
          Menu.class.getResource("/imgs/rotom.jpg"));  
          g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);  
        }  
};  

And adding the following classes:

 import java.awt.Graphics;  
 import java.awt.Image;  
 import java.awt.Toolkit;  

But to no avail the window remains with its dull grey color, so far my code is just the standard one WindowsBuilder cooks for you plus 4 buttons but I doubt they're of importance here. Shouldn't the code I added override the paintComponent() method of the jPanel and draw the image in it?

The class for the menu is in a package within my project and the image is within a imgs package is within the same project as well.

Thanks a lot in advance.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Code Grasshopper
  • 610
  • 1
  • 11
  • 29
  • 1
    Don't try to load resources in a paint method. Load them as a class attribute and simply draw them in paint. – Andrew Thompson Jun 12 '14 at 03:30
  • @AndrewThompson Sorry as I said I am very new to this, do you think you could provide me a example? – Code Grasshopper Jun 12 '14 at 03:33
  • I also recommend to use `ImageIO.read(URL)` to load the image, since it provides more feed-back on failure. – Andrew Thompson Jun 12 '14 at 03:33
  • I was using the following tutorial: http://tjisblogging.blogspot.com/2013/04/how-to-set-background-image-to-jframe.html I assume the method used here is incorrect? – Code Grasshopper Jun 12 '14 at 03:34
  • 1
    *"do you think you could provide me a example?"* Do you think you could you pay me? SO is a Q&A site, not a code generation factory. – Andrew Thompson Jun 12 '14 at 03:35
  • Actually yes I could. – Code Grasshopper Jun 12 '14 at 03:36
  • That first comment was sarcasm, BTW. I am not accepting consultancy work at the moment. As to the blog, the author is truly an amateur, they also try to load the resource in the paint method. You won't learn anything (good) from that code. Time to find a new learning resource. – Andrew Thompson Jun 12 '14 at 03:38
  • In answer to your question *"Shouldn't the code I added override the paintComponent() method of the jPanel and draw the image in it?"* For a `JComponent` like a `JPanel`, yes, `@Override .. paintComponent(Graphics)` as the code seen in the question is doing. But we should always immediately call the `super` method and *never try to **load** a resource such as an image* within the method, since it is supposed to start and finish quickly. -- Would you accept that as an answer? If not, I'm not sure what the question is. – Andrew Thompson Jun 12 '14 at 03:42
  • 1
    @CodeGrasshopper: Please have a look at how to [add images to Eclipse Project](http://stackoverflow.com/a/9866659/1057230). Hopefully this might be able to help somewhat :-) – nIcE cOw Jun 12 '14 at 03:48

1 Answers1

4

A simple method, if you're not interested in resizing the background image or applying any effects is to use a JLabel...

BufferedImage bg = ImageIO.read(Menu.class.getResource("/imgs/rotom.jpg"));
JLabel label = new JLabel(new ImageIcon(bg));
setContentPane(label);
setLayout(...);

There are limitations to this approach (beyond scaling), in that the preferred size of the label will always be that of the image and never take into account it's content. This is both good and bad.

The other approach, which you seem to be using, is to use a specialised component

public class BackgroundPane extends JPanel {

    private BufferedImage img;

    public BackgroundPane(BufferedImage img) {
        this.img = img;
    }

    @Override
    public Dimension getPreferredSize() {
        return img == null ? super.getPreferredSize() : new Dimension(img.getWidth(), img.getHeight());
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(img, 0, 0, this);
    }
}

You should avoid trying to perform any task in the paintComponent method which may take time to complete as paintComponent may be called often and usually in quick succession....

Getting the image to scale when the component is resized is an entire question into of it self, for some ideas, you could take a look at...

Oh, and, you should avoid extending directly from top level containers, like JFrame, they reduce the reusability for your components and lock you into a single container

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366