There are any number of ways this might be achieved.
You Could...
Disclaimer
Cavet, using a JLabel
for this purpose may result in the contents over spilling the continer, see below for more details
Create a JLabel
, apply the image to it's icon
property and set this as the frames content pane. You would then need to set the layout manager appropriately, as JLabel
doesn't have a default layout manager
JFrame frame = ...;
JLabel background = new JLabel(new ImageIcon(ImageIO.read(...)));
frame.setContentPane(background);
frame.setLayout(...);
frame.add(...);
Update with full example
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class LabelBackground {
public static void main(String[] args) {
new LabelBackground();
}
public LabelBackground() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
// Load the background image
BufferedImage img = ImageIO.read(new File("/path/to/your/image/on/disk"));
// Create the frame...
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Set the frames content pane to use a JLabel
// whose icon property has been set to use the image
// we just loaded
frame.setContentPane(new JLabel(new ImageIcon(img)));
// Supply a layout manager for the body of the content
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
// Add stuff...
frame.add(new JLabel("Hello world"), gbc);
frame.add(new JLabel("I'm on top"), gbc);
frame.add(new JButton("Clickity-clackity"), gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
});
}
}
The problem with this is the JLabel
won't resize the image when the frame is resized
WARNING - Using a JLabel
could cause issues if the required space of the child components exceeds the size of the background image, as JLabel
does not calculate it's preferred size based on it's contents, but based on its icon
and text
properties
You Could...
Create a custom component, extending from something like JPanel
and override it's paintComponent
method, painting the background as you see fit.
Take a look at Performing Custom Painting for more details.
This provides you with the ability to decide how best the image should be scaled when it's available space changes. While there are a number of ways this might be achived, you should read through The Perils of Image.getScaledInstance() to understand the pros and cons of them.
This raises a bunch of new questions, to you want to scale them and preserve the aspect ratio? If so, do you want to fit the image to available area or fill it (so it will always cover the available space)?
Take a look at Java: maintaining aspect ratio of JPanel background image for more details.
Other considerations
Images are generally best loaded through the ImageIO
API, as it's capable of loading a wide range of images, but will also throw an IOException
when something goes wrong.
See Reading/Loading an Image for more details.
The location of the image is also important. If the image is external to the application (somewhere on the file system), you can use ImageIO.read(new File("/path/to/image"))
. However, if the the image is embedded within your application (stored within the Jar for example), you will need to use something more like ImageIO.read(getClass().getResource("/path/to/image"))
instead...
For example...
Example
This example demonstrates the use of a custom component which acts as the background component. When the components size exceeds the size of the background image, the image is scaled up to fill the available content area.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SimpleBackground {
public static void main(String[] args) {
new SimpleBackground();
}
public SimpleBackground() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
BackgroundPane background = new BackgroundPane();
background.setBackground(ImageIO.read(new File("/path/to/your/image/on/your/disk")));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(background);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
frame.add(new JLabel("Hello world"), gbc);
frame.add(new JLabel("I'm on top"), gbc);
frame.add(new JButton("Clickity-clackity"), gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
});
}
public class BackgroundPane extends JPanel {
private BufferedImage img;
private BufferedImage scaled;
public BackgroundPane() {
}
@Override
public Dimension getPreferredSize() {
return img == null ? super.getPreferredSize() : new Dimension(img.getWidth(), img.getHeight());
}
public void setBackground(BufferedImage value) {
if (value != img) {
this.img = value;
repaint();
}
}
@Override
public void invalidate() {
super.invalidate();
if (getWidth() > img.getWidth() || getHeight() > img.getHeight()) {
scaled = getScaledInstanceToFill(img, getSize());
} else {
scaled = img;
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (scaled != null) {
int x = (getWidth() - scaled.getWidth()) / 2;
int y = (getHeight() - scaled.getHeight()) / 2;
g.drawImage(scaled, x, y, this);
}
}
}
public static BufferedImage getScaledInstanceToFill(BufferedImage img, Dimension size) {
double scaleFactor = getScaleFactorToFill(img, size);
return getScaledInstance(img, scaleFactor);
}
public static double getScaleFactorToFill(BufferedImage img, Dimension size) {
double dScale = 1;
if (img != null) {
int imageWidth = img.getWidth();
int imageHeight = img.getHeight();
double dScaleWidth = getScaleFactor(imageWidth, size.width);
double dScaleHeight = getScaleFactor(imageHeight, size.height);
dScale = Math.max(dScaleHeight, dScaleWidth);
}
return dScale;
}
public static double getScaleFactor(int iMasterSize, int iTargetSize) {
double dScale = (double) iTargetSize / (double) iMasterSize;
return dScale;
}
public static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor) {
return getScaledInstance(img, dScaleFactor, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);
}
protected static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor, Object hint, boolean bHighQuality) {
BufferedImage imgScale = img;
int iImageWidth = (int) Math.round(img.getWidth() * dScaleFactor);
int iImageHeight = (int) Math.round(img.getHeight() * dScaleFactor);
// System.out.println("Scale Size = " + iImageWidth + "x" + iImageHeight);
if (dScaleFactor <= 1.0d) {
imgScale = getScaledDownInstance(img, iImageWidth, iImageHeight, hint, bHighQuality);
} else {
imgScale = getScaledUpInstance(img, iImageWidth, iImageHeight, hint, bHighQuality);
}
return imgScale;
}
protected static BufferedImage getScale