Search code examples
javaswinglayoutgridbaglayoutjlayeredpane

Using GridBagLayout in a JLayeredPane


I am attempting to have a small floating "widget" of sorts in the top right of a JPanel. It's a fixed-size component - think of the compass in a google maps sort of view, if that helps.

I realize that JLayeredPane only uses one layout manager for all the layers and so thought that using GBL with be successful: - make the top right (1, 0) box very small and put the widget there - make the content panel be of width/height 2

But after experimenting, it seems that GBL removes some components when they overlap.

Can anyone suggest a way of faking this behaviour?


Solution

  • It's a layered pane, and so each layer can have a container that uses its own layout if desired. I wouldn't give the JLayeredPane itself any layout at all but rather use its default null layout and then would consider putting the small floating widget in a transparent (non-opaque) JPanel that uses any layout desired and add the transparent JPanel to an upper layer of the JLayeredPane.

    For example this code puts an image of a compass in the upper right corner of a non-opaque JPanel that is layered over a JLabel that shows a relief map:

    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.net.URL;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class LayeredExample extends JLayeredPane {
       public static final String MAP_URL = "http://upload.wikimedia.org/" +
            "wikipedia/commons/c/c4/Maps-for-free_Sierra_Nevada.png";
       public static final String COMPASS_URL = "http://upload.wikimedia.org/" +
            "wikipedia/commons/thumb/f/f8/Compass_Rose_English_North.svg/" +
            "200px-Compass_Rose_English_North.svg.png";
       private Dimension imageSize;
       private JLabel defaultLabel = new JLabel();
       private JPanel palettePane = new JPanel();
       private JLabel compassLabel = new JLabel();
    
       public LayeredExample() {
          try {
             URL mapUrl = new URL(MAP_URL);
             BufferedImage mapImage = ImageIO.read(mapUrl);
             ImageIcon mapIcon = new ImageIcon(mapImage);
             defaultLabel.setIcon(mapIcon);
    
             URL compassUrl = new URL(COMPASS_URL);
             BufferedImage compassImage = ImageIO.read(compassUrl);
             ImageIcon compassIcon = new ImageIcon(compassImage);
             compassLabel.setIcon(compassIcon);
    
             imageSize = new Dimension(mapImage.getWidth(), mapImage.getHeight());
             setPreferredSize(imageSize);
             defaultLabel.setSize(imageSize);
             defaultLabel.setLocation(0, 0);
             palettePane.setSize(imageSize);
             palettePane.setLocation(0, 0);
    
    
             JPanel northPalettePane = new JPanel(new BorderLayout());
             northPalettePane.setOpaque(false);
             northPalettePane.add(compassLabel, BorderLayout.EAST);
             palettePane.setOpaque(false);
             palettePane.setLayout(new BorderLayout());
             palettePane.add(northPalettePane, BorderLayout.NORTH);
    
             add(defaultLabel, JLayeredPane.DEFAULT_LAYER);
             add(palettePane, JLayeredPane.PALETTE_LAYER);
          } catch (MalformedURLException e) {
             e.printStackTrace();
          } catch (IOException e) {
             e.printStackTrace();
          }
       }
    
       private static void createAndShowUI() {
          JFrame frame = new JFrame("LayeredExample");
          frame.getContentPane().add(new LayeredExample());
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          java.awt.EventQueue.invokeLater(new Runnable() {
             public void run() {
                createAndShowUI();
             }
          });
       }
    }