Search code examples
javaswingjpaneljcomponent

Custom component is not shown on JPanel


I am new to the java swing library and am trying to create my own components. In this case I have a Circle class extending the JComponent class. However, when trying to add an instance of the Circle class to my JPanel, the circle isn't displaying (only the JPanel).

I am aware that drawing directly to the JPanel with the Graphics class would be simpler, but I want to be able to create my own visuals class.

This is my code:

import javax.swing.; import java.awt.;

public class Main{
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JPanel myPanel = new JPanel();
        myPanel.setBackground(Color.CYAN);
        frame.setSize(500, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myPanel.add(new Circle());
        frame.add(myPanel);
        frame.setVisible(true);
    }
}
import javax.swing.*;
import java.awt.*;

public class Circle extends JComponent {
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.RED);
        g.fillOval(50, 50, 100, 100);
    }
}

When running this code, only the cyan background of the JPanel is appearing. Is the JPanel covering the red circle? Have I overriden the paintComponent method incorectly?


Solution

  • Your component has no size. Try it like this.

    class Circle extends JComponent {
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.fillOval(50, 50, 100, 100);
        }
        @Override
        // prevents someone from changing size via instance, if desired.
        public Dimension getPreferredSize() {
            return new Dimension(150,150);
        }
        
    }
    

    You may want to modify your other code as follows:

    • don't set the size in the Frame as that also includes all border widths so your panel would be smaller than 500 x 500. Set it in the JPanel and the Frame will be sized to accommodate it.
    • use frame.pack to apply layout sizes and other attributes
    • use frame.setLocationRelativeTo(null) to center frame on screen.
    frame.pack();                      
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);                                           
    

    And you may also want to create a custom JPanel similar to your custom component to also have more control over the size.

    Check the API JavaDocs for more information. Also check out the Java Tutorials section on custom painting.