Search code examples
javaswinggraphicsjpanelpaintcomponent

Java JPanel paintComponent(Graphics g) not called


I have a JPanel whose paintComponent(Graphics g) method is not being called. I know that this is a common problem, but none of the suggestions I've found so far have been able to fix it. Here is the code for the JPanel:

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

public class Grid extends JPanel

{
    Candy[][] gridRep = new Candy[8][8];
    public Grid()

    {
        this.setLayout(new GridLayout(8,8));
        this.populateRandom();
        this.repaint();
    }

    ...

    public void paintComponent(Graphics g){
        Graphics2D g2 = (Graphics2D)g;
        for (int r = 0; r<8; r++){
            for (int c = 0; c<8; c++){
                g2.setColor(gridRep[r][c].getColor());
                g2.drawOval(getXCoordinate(gridRep[r][c])*15, getYCoordinate(gridRep[r][c])*15, 10, 10);
                System.out.println("repainting");
            }
        }
    }

}

As you can see, I call repaint() in the constructor, but that does nothing. I also call it willy nilly in the JFrame class that creates an object of this class:

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

public class Game
{
    private Grid grid;
    private JFrame frame;
public Game(){
this.makeFrame();
}

private void makeFrame(){
    grid = new Grid();
    frame = new JFrame ("Frame");
    Container contentPane = frame.getContentPane();
    contentPane.setLayout(new FlowLayout());
    //grid.paint(grid.getGraphics());
    grid.repaint();
    frame.add(grid);
    grid.repaint();
    frame.pack();
    grid.repaint();
    frame.setVisible(true);
    grid.repaint();
}

Solution

  • As you can see, I call repaint() in the constructor, but that does nothing

    You don't need to invoke repaint(). Swing will determine when repainting needs to be done.

    Anyway in this case it does nothing because the component hasn't been added to the GUI yet.

     contentPane.setLayout(new FlowLayout());
    

    You are using a FlowLayout which respects a components size. Your custom component where you do the painting doesn't have a preferred size so its size is (0, 0) so there is nothing to paint.

    Override the getPreferredSize() method to return the size of the component. It looks like each grid is (15, 15), so you should use:

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

    Of course it would be better to define variable for you class to contain the grid size and the number of grids rather than hard codeing 8 and 15 through out your code.