Layering multiple GlassPane's in a Root Container

Is it possible to add multiple GlassPanes for a single JFrame, or do I have to use the uncomfortable LayeredPane with the Opacity attribute.

I have attached some code that shows what I want to do (provided by @camickr).

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;

public class MultiplayGlassPane {

    private static final long serialVersionUID = 1L;
    private JFrame frame = new JFrame("frameTitle");
    private JPanel fPanel = new JPanel();
    private Random random = new Random();
    private final static Border MESSAGE_BORDER = new EmptyBorder(10, 10, 10, 10);
    private JLabel message = new JLabel();
    private ArrayList<Star> stars = new ArrayList<Star>();

    public MultiplayGlassPane() {

        MyGlassPane glass = new MyGlassPane();
        for (int i = 0; i < 35; i++) {
            Star star = new Star(new Point(random.nextInt(580), random.nextInt(550)));
            star.setColor(Color.orange);
            star.setxIncr(-3 + random.nextInt(7));
            star.setyIncr(-3 + random.nextInt(7));
            glass.add(star);
        }
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(glass, BorderLayout.CENTER);
        frame.setLocation(20, 20);
        frame.pack();
        frame.setVisible(true);

        DisabledGlassPane1 glassPane = new DisabledGlassPane1();
        JRootPane rootPane = SwingUtilities.getRootPane(frame);
        rootPane.setGlassPane(glassPane);
        glassPane.activate("");
    }

    private class MyGlassPane extends JLabel {

        private static final long serialVersionUID = 1L;
        private ArrayList<Star> stars = new ArrayList<Star>();
        private javax.swing.Timer timer = new javax.swing.Timer(20, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                for (Star star : stars) {
                    star.move();
                }
                repaint();
            }
        });

        public void stopAnimation() {
            if (timer.isRunning()) {
                timer.stop();
            }
        }

        public void startAnimation() {
            if (!timer.isRunning()) {
                timer.start();
            }
        }

        @Override
        public void addNotify() {
            super.addNotify();
            timer.start();
        }

        @Override
        public void removeNotify() {
            super.removeNotify();
            timer.stop();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(new Dimension(620, 620));
        }

        public MyGlassPane() {
            this.setPreferredSize(new Dimension(620, 620));
        }

        public void add(Star star) {
            stars.add(star);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            for (Star star : stars) {
                g.setColor(star.getColor());
                g.fillPolygon(star);
            }
        }
    }

    class DisabledGlassPane1 extends JComponent implements KeyListener {

        private static final long serialVersionUID = 1L;

        public DisabledGlassPane1() {
            setOpaque(false);
            Color base = UIManager.getColor("inactiveCaptionBorder");
            Color background = new Color(base.getRed(), base.getGreen(), base.getBlue(), 128);
            setBackground(background);
            setLayout(new GridBagLayout());
            add(message, new GridBagConstraints());
            message.setOpaque(true);
            message.setBorder(MESSAGE_BORDER);
            addMouseListener(new MouseAdapter() {
            });
            addMouseMotionListener(new MouseMotionAdapter() {
            });
            addKeyListener(this);
            setFocusTraversalKeysEnabled(false);
            Random random = new Random();
            for (int i = 0; i < 50; i++) {
                Star star = new Star(new Point(random.nextInt(490), random.nextInt(490)));
                star.setColor(Color.magenta);
                star.setxIncr(-3 + random.nextInt(7));
                star.setyIncr(-3 + random.nextInt(7));
                add(star);
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            for (Star star : stars) {
                g.setColor(star.getColor());
                g.fillPolygon(star);
            }
        }

        @Override
        public void setBackground(Color background) {
            super.setBackground(background);
            Color messageBackground = new Color(background.getRGB());
            message.setBackground(messageBackground);
        }

        public void keyPressed(KeyEvent e) {
            e.consume();
        }

        public void keyTyped(KeyEvent e) {
        }

        public void keyReleased(KeyEvent e) {
            e.consume();
        }

        public void activate(String text) {
            if (text != null && text.length() > 0) {
                message.setVisible(true);
                message.setText(text);
                message.setForeground(getForeground());
            } else {
                message.setVisible(false);
            }
            setVisible(true);
            //setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
            requestFocusInWindow();
        }

        public void deactivate() {
            setCursor(null);
            setVisible(false);
        }
        private javax.swing.Timer timer = new javax.swing.Timer(15, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                for (Star star : stars) {
                    star.move();
                }
                repaint();
            }
        });

        public void stopAnimation() {
            if (timer.isRunning()) {
                timer.stop();
            }
        }

        public void startAnimation() {
            if (!timer.isRunning()) {
                timer.start();
            }
        }

        @Override
        public void addNotify() {
            super.addNotify();
            timer.start();
        }

        @Override
        public void removeNotify() {
            super.removeNotify();
            timer.stop();
        }

        public void add(Star star) {
            stars.add(star);
        }
    }

    private class Star extends Polygon {

        private static final long serialVersionUID = 1L;
        private Point location = null;
        private Color color = Color.YELLOW;
        private int xIncr, yIncr;
        static final int WIDTH = 600, HEIGHT = 600;

        Star(Point location) {
            int x = location.x;
            int y = location.y;
            this.location = location;
            this.addPoint(x, y + 8);
            this.addPoint(x + 8, y + 8);
            this.addPoint(x + 11, y);
            this.addPoint(x + 14, y + 8);
            this.addPoint(x + 22, y + 8);
            this.addPoint(x + 17, y + 12);
            this.addPoint(x + 21, y + 20);
            this.addPoint(x + 11, y + 14);
            this.addPoint(x + 3, y + 20);
            this.addPoint(x + 6, y + 12);
        }

        public void setColor(Color color) {
            this.color = color;
        }

        public void move() {
            if (location.x < 0 || location.x > frame.getContentPane().getWidth() - 20) {
                xIncr = -xIncr;
            }
            if (location.y < 0 || location.y > frame.getContentPane().getHeight() - 20) {
                yIncr = -yIncr;
            }
            translate(xIncr, yIncr);
            location.setLocation(location.x + xIncr, location.y + yIncr);
        }

        public void setxIncr(int xIncr) {
            this.xIncr = xIncr;
        }

        public void setyIncr(int yIncr) {
            this.yIncr = yIncr;
        }

        public Color getColor() {
            return color;
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                MultiplayGlassPane Mpgp = new MultiplayGlassPane();
            }
        });
    }
}

Solution 1:

Look at http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html for an explanation on Root panes and what the Glass pane actually is.

The glass pane is just a convenient way to add a component which has the size of the Root Pane, and which blocks all input events. This allows you to catch any interaction with your components to create a "Please wait..." screen.

There is only a single glass pane per root container. You cannot layer glass panes.

You can replace the contents of the glass pane by something else if you want to layer something over the current glass pane. You can also set a JPanel as a glass pane, which allows you to layout multiple components in the glass pane.

Usually, you should only use the glass pane to block user input (and, if necessary, display some kind of "please wait" message). Can you provide a use case of why you want to put glass panes on top of one another?