Search code examples
javaswingpaintcomponentjlayeredpane

Drawing to JPanel on Layered Pane


What I'm looking to do is custom draw to a JPanel that is attached to one of the layers in a layered pane.

For simple drawing I get that you can effectively do the following:-

JFrame frame = new JFrame();
frame.add(new CustomPaintComponent());

I have this and the CustomPaintComponent is called, drawing to a test frame created - all works fine. However...if I try the same approach (below) but using pane instead of frame the CustomPaintComponent isn't even called let alone producing the same drawing I get when adding simply to the frame.

pane.add(new CustomPaintComponent(),JLayeredPane.POPUP_LAYER);

I'd be grateful for any support/advice on this. Why isn't the method being called - should I be doing something (maybe a lot :P) differently?

Simple Example Below

Example Class which creates the JFrame and JLayeredPane and JPanel (the latter accesses second class below)

package example;

import javax.swing.*;

public class Example {

    public static void main(String[] args) {
        
        JLayeredPane forLayers = new JLayeredPane();
        forLayers.setSize(300, 300);
        
        JFrame showsDrawnImage = new JFrame ("JFrame");
        showsDrawnImage.setSize(300, 300);
        
        JPanel panelDrawnOn = new DrawImage();
        
        //CODE BELOW WORKS - and returns string line in output//
        
        showsDrawnImage.add(panelDrawnOn); //blank these out to show the layeredpane example
        showsDrawnImage.setVisible(true); //blank these out to show the layeredpane example
        
        //CODE BELOW DOESN'T WORK - only shows the JFrame and DOES NOT return string line in output//

        forLayers.add(panelDrawnOn, JLayeredPane.PALETTE_LAYER);
        showsDrawnImage.add(forLayers);
        forLayers.setVisible(true);
        showsDrawnImage.setVisible(true);

    }
    
}

DrawImage class to do the actual drawing

package example;

import java.awt.*;
import java.awt.geom.*;
import javax.swing.JPanel;

public class DrawImage extends JPanel{
    
    public void paintComponent( Graphics g ) {
        
                    System.out.println("This is what I try to access/draw");
                    
                    super.paintComponent(g);
                    Graphics2D g2 = (Graphics2D)g;

                    Line2D line = new Line2D.Double(10, 10, 40, 40);
                    g2.setColor(Color.blue);
                    g2.setStroke(new BasicStroke(10));
                    g2.draw(line);
 
                 }
    
}

Solution

  • I would guess the main issue is that your custom component doesn't have a "size" so there is nothing to paint.

    When you add a component to a JFrame, the layout manager will give the components a size. A JLayeredPane doesn't use layout managers, so it is now your responsibility to give the component a size and location.

    Read the section from the Swing tutorial on How to Use Layered Panes for a working example.

    Also, don't use the POPUP_LAYER. That is meant to be used for temporary display of a component only.