Gabriel
Gabriel

Reputation: 21

Drawing a JComponent inside a JPanel

I am trying to display a JComponent inside a JPanel. I am using null layout because location of the components can be changed during runtime and I have to control them.

But the following code does not work. The JComponent only becomes visible on display if I explicity call the "paintComponent" method, which I think is not good practice.

My JComponent Class

public class MyIcon extends JComponent 
{
    private double xPos;
    private double yPos;
    private double radius = 30;

    public MyIcon(double xPos, double yPos)
    {
            this.xPos = xPos;
            this.yPos = yPos;
            this.setBounds((int)xPos, (int)yPos, (int)radius, (int)radius);
            this.setPreferredSize(new Dimension((int)radius, (int)radius ) );
    }

    public Dimension getPreferredSize()
    {
            return ( new Dimension( (int)radius, (int)radius ) );
    }

    public Dimension getMinimumSize() 
    {
            return new Dimension((int)radius, (int)radius);
    }


    public void paintComponent(Graphics g)
    {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.setColor(Color.BLACK);
            g2d.drawOval( (int)xPos, (int)yPos, (int)radius, (int)radius);

            g2d.fillOval((int)xPos, (int)yPos, (int)radius, (int)radius);

            System.out.println("Icon.paintComponnet() called");
    }
}

My Panel Class

public class MyPanel extends JPanel
{
    private MyIcon myIcon;
    private Graphics2D graphics;
    private int width = 700;
    private int height = 500;

    public MyPanel()
    {
        myIcon = new MyIcon(20,30);
        init();
    }

    private void init()
    {
        setLayout(null);
        setBackground(Color.WHITE);
        setPreferredSize( new Dimension(width, height) );
        setBorder(BorderFactory.createLineBorder(Color.BLACK));
        add( myIcon );
        myIcon.repaint();       
    }

    public void paintComponent(Graphics g)
    {
        graphics = (Graphics2D) g;
        super.paintComponent(g);
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        System.out.println("MyPanel.paintComponnet() called");

        // why my Icon only gets painted if I explicitly call for it ?

        //myIcon.paintComponent(g);
    }
}

My Frame Class

public class Editor {

    public static void main(String[] args)
    {
        Editor editor = new Editor();
    }

    private MyPanel myPanel;
    private JFrame frame;
    private JToolBar toolBar;

    public Editor()
    {
        myPanel = new MyPanel();
        init();
    }

    private void init()
    {
        frame = new JFrame("Editor");
        Container content = frame.getContentPane();
        frame.setSize(800, 600);
        frame.setLayout(new BorderLayout(15,15));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        content.add(myPanel,BorderLayout.WEST);

        frame.pack();
        frame.setVisible(true);
     }
}

Upvotes: 2

Views: 2113

Answers (2)

Dan D.
Dan D.

Reputation: 32391

Maybe a good approach would be that the Icon class would not extend JComponent but would be just a simple object.

Then, you rename the current Icon.paintComponent you have to something like drawIcon and call the drawIcon method from the MyPanel.paintComponent directly and passing the reference to the Graphics object.

This way you don't have to wonder about using a null layout and you can control the place to display the icon to by just using the Graphics(2d) APIs.

Upvotes: 1

Related Questions