Adding JPanel inside a JPanel - the nested JPanel won't display

java, swing, xor

Solution

The major problem is here...

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Color c = Color.cyan;
        g.setColor(c);
        g.fillRect(0, 0,getWidth(), getHeight());
        add(b);
        repaint();
    }

Not only are adding components to your container within you paint method, you're also calling repaint, all this is going to conspire against you.

Paint is called by the repaint manager when ever your component needs to be updated, for all sorts of reasons. You should never call any methods that might invalidate it otherwise require the component to repainted, doing so will send you down slippery slope of CPU burn out.

Instead.

- Add your `Bubble` component inside the constructor of the `Background` component

- Override the `getPreferredSize` methods of both these components and provide useful hints so the layout managers have some idea of how much space the components might actually like to use

The major problem you are facing (other then the bad painting) is that the components are reporting themselves as requiring no height or width, meaning when the layout managers come to lay them out, they are effectively invisible

Update

I would recommend that you have a look at

- Creating a GUI with Swing, paying special attention to the section on layout managers

- Custom painting

- Painting in AWT and Swing

Easter Egg

For taking advice and making an effort, let me give you a little help...

What I suggest you do is read through the code, go back to the Java Docs and tutorials and try and figure out what is going on ;)

public class CircleControl {

    public static void main(String[] args) {
        new CircleControl();
    }

    public CircleControl() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            add(new Bubble());
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g.create();

            Color startColor = brighten(Color.CYAN, 0.75f);
            Color endColor = brighten(Color.CYAN, 0.5f);

            LinearGradientPaint lgp = new LinearGradientPaint(
                            new Point(0, 0),
                            new Point(0, getHeight()),
                            new float[]{0f, 1f},
                            new Color[]{startColor, endColor});

            g2d.setPaint(lgp);
            g2d.fill(new Rectangle(getWidth(), getHeight()));
            g2d.dispose();

        }
    }

    public class Bubble extends JPanel {

        public Bubble() {
            Font font = UIManager.getFont("Label.font");
            setFont(font.deriveFont(Font.BOLD, 48));
            setForeground(Color.WHITE);
            setBackground(darken(Color.CYAN, 0.3f));
            setOpaque(false);
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            
            int x = (getWidth() - 150) / 2;
            int y = (getHeight() - 150) / 2;

            Color startColor = brighten(getBackground(), 0.05f);
            Color endColor = getBackground();

            LinearGradientPaint lgp = new LinearGradientPaint(
                            new Point(x, y),
                            new Point(x, y + 150),
                            new float[]{0f, 1f},
                            new Color[]{startColor, endColor});
            g2d.setPaint(lgp);
            g2d.fill(new Ellipse2D.Double(x, y, 150, 150));
            
            FontMetrics fm = g2d.getFontMetrics();
            x = x + ((150 - fm.stringWidth("22")) / 2);
            y = y + ((150 / 2) + fm.getAscent());
            g2d.setColor(getForeground());
            g2d.drawString("22", x, y);

        }
    }

    public static Color brighten(Color color, double fraction) {
        int red = (int) Math.round(Math.min(255, color.getRed() + 255 * fraction));
        int green = (int) Math.round(Math.min(255, color.getGreen() + 255 * fraction));
        int blue = (int) Math.round(Math.min(255, color.getBlue() + 255 * fraction));
        int alpha = color.getAlpha();
        return new Color(red, green, blue, alpha);
    }

    public static Color darken(Color color, double fraction) {
        int red = (int) Math.round(Math.max(0, color.getRed() - 255 * fraction));
        int green = (int) Math.round(Math.max(0, color.getGreen() - 255 * fraction));
        int blue = (int) Math.round(Math.max(0, color.getBlue() - 255 * fraction));
        int alpha = color.getAlpha();
        return new Color(red, green, blue, alpha);
    }
}

Problem

New Code ``` package test; import javax.swing.*; import java.awt.*; public class TestWindow extends JFrame{ //------------------------------------------------------------------------------ public static void main(String[] args) { new TestWindow(); } //------------------------------------------------------------------------------ public TestWindow(){ setSize(300,300); this.setUndecorated(true); add(new Background()); setVisible(true); } //------------------------------------------------------------------------------ private class Background extends JPanel{ public Background(){ add(b); repaint(); } //------------------------------------------------------------------------------ Bubble b = new Bubble(); @Override public void paintComponent(Graphics g){ super.paintComponent(g); Color c = Color.cyan; g.setColor(c); g.fillRect(0, 0,getWidth(), getHeight()); } //------------------------------------------------------------------------------ private class Bubble extends JPanel{ @Override public void paintComponent(Graphics g){ super.paintComponent(g); g.setColor(Color.green); g.drawOval(0, 0, Background.this.getWidth(), Background.this.getHeight()); } } //------------------------------------------------------------------------------ } } ``` Output Problem The aim is to draw a cyan window with a green circle on it. Later I will add components to the green circle so it will look like there is a window with a cyan background and a green circle with components in it. The output however is only the cyan background. No circle. I tried setting XOR mode to cyan but that did not work either. Am I nesting the classes wrong?

Original source