The main approach to this problem is to use JLayeredPane and something like GridBagLayout .
JLayeredPane will give you better control over the z-depth of various levels, and GridBagLayout will allow you to assemble components as needed.
You can also take a look at OverlayoutLayout , but never using it, I can not comment.

import java.awt.BorderLayout; 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.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLayeredPane; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class MapLayers { public static void main(String[] args) { new MapLayers(); } public MapLayers() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } MapPane mapPane = new MapPane(); try { mapPane.addLayer(new ImageLayer(ImageIO.read(new File("Ponie.png")), 360, 10)); mapPane.addLayer(new ImageLayer(ImageIO.read(new File("Layer01.png")), 0, 0)); } catch (IOException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(mapPane); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class ImageLayer extends JComponent { private Image bg; private int xOffset; private int yOffset; public ImageLayer(Image image, int x, int y) { bg = image; xOffset = x; yOffset = y; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (bg != null) { Graphics2D g2d = (Graphics2D) g.create(); g2d.drawImage(bg, xOffset, yOffset, this); g2d.dispose(); } } } public class MapPane extends JLayeredPane { private BufferedImage bg; public MapPane() { try { bg = ImageIO.read(new File("PirateMap.jpg")); } catch (IOException exp) { exp.printStackTrace(); } setLayout(new GridBagLayout()); } public void addLayer(JComponent layer) { GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = 1; gbc.weighty = 1; gbc.fill = GridBagConstraints.BOTH; add(layer, gbc); } @Override public Dimension getPreferredSize() { return bg == null ? new Dimension(200, 200) : new Dimension(bg.getWidth(), bg.getHeight()); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (bg != null) { Graphics2D g2d = (Graphics2D) g.create(); int x = (getWidth() - bg.getWidth()) / 2; int y = (getHeight()- bg.getHeight()) / 2; g2d.drawImage(bg, x, y, this); g2d.dispose(); } } } }
See How to use LayeredPanes for more information.
source share