Using GridBagLayout in a JLayeredPane

Issue

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();
         }
      });
   }
}

Answered By – Hovercraft Full Of Eels

Leave a Comment