This question already has an answer here:
public class Board extends JFrame { public void bd() { JFrame frame=new JFrame(); JLabel background1 = new JLabel(new ImageIcon("background.png")); JLabel knight=new JLabel(new ImageIcon("knight.jpg")); frame.add(background1); frame.add(knight); frame.pack(); frame.setResizable(false); frame.setVisible(true); } }
I've been having some trouble with my code
when i add the knight image the background image will disappear and only the knight image appears. How would i make the images overlap or make the background image act like a background
JLabel background1 = new JLabel(new ImageIcon("background.png")); JLabel knight=new JLabel(new ImageIcon("knight.jpg")); frame.add(background1); frame.add(knight);
I'm guessing what you really want is have the knight displayed on top (on the z axis) so you need to do something like:
JLabel background1 = new JLabel(new ImageIcon("background.png")); background.setLayout( new BorderLayout() ); JLabel knight=new JLabel(new ImageIcon("knight.jpg")); background1.add(knight); frame.add(background1);
That is you need to follow a parent/child hierarchy:
- add the background to the frame
- add the knight to the background
JFrame
uses BorderLayout
by default, which means only one image is managed at the default/CENTER
position.
See How to Use Borders for more details.
The solution is actually difficult, because you need to be able to make guarantees about the size of the layout, the images and the board
You might be able to use a GridLayout
or GridBagLayout
, but you'd need to have "empty" filler components to allow the layout to correctly expand, which could be come troublesome
Maybe a better solution might be to use a custom painting approach, which give you control over where the images are placed.
Painting in AWT and Swing and Performing Custom Painting for more detals
The following example simply makes use of GridBagLayout
, which allows you to overlay components (in a variety of different ways). This example makes the boardLabel
the container for all the other pieces, but, because the way GridBagLayout
works, this isn't an absolute requirement

import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.image.BufferedImage; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class Chess { public static void main(String[] args) { new Chess(); } public Chess() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } catch (IOException ex) { ex.printStackTrace(); } } }); } public class TestPane extends JPanel { public TestPane() throws IOException { BufferedImage board = ImageIO.read(getClass().getResource("/board.png")); BufferedImage knight = ImageIO.read(getClass().getResource("/Knight.png")); setLayout(new BorderLayout()); JLabel boardLabel = new JLabel(new ImageIcon(board)); add(boardLabel); boardLabel.setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); for (int row = 0; row < 8; row++) { gbc.gridy = row; for (int col = 0; col < 8; col++) { gbc.gridx = col; boardLabel.add(filler(), gbc); } } JLabel knightLabel = new JLabel(new ImageIcon(knight)); gbc.gridx = 3; gbc.gridy = 4; boardLabel.add(knightLabel, gbc); } protected JComponent filler() { JLabel filler = new JLabel() { @Override public Dimension getPreferredSize() { return new Dimension(50, 50); } }; return filler; } } }
With a setup like this, you can simply use GridBagConstraint
's gridx
and gridy
values as direct cell address (no need to calculate the pixel position).
Because of the way the layout manager works, you are required to provide an empty cell component as well