Search code examples
javaswinggraphicsjpanelpaintcomponent

JPanel does not refresh Graphics component on resize


This program is supposed to draw a grid of Rectangles in a JPanel. I drew the grid onto the JPanel by overriding its paintComponent method so that every time the JPanel resizes, the size of the grid would change to fit the height of the JPanel. But when I change the size of the JFrame, the grid only resizes at certain intervals. Is there a better way to change the size of the grid?

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

class TextFrame extends JPanel
{
int numOfCells = 99;
int cellSize, xOffSet;
Rectangle2D.Float[][] square = new Rectangle2D.Float[numOfCells][numOfCells];

public TextFrame()
{
    setSize(400, 400);
}

public void paintComponent(Graphics comp)
{
    Graphics2D comp2d = (Graphics2D)comp;

    cellSize = (int)getHeight()/numOfCells;
    if(getWidth()<=cellSize*numOfCells)
        cellSize = getWidth()/numOfCells;
    xOffSet = (getWidth()-(cellSize*numOfCells))/2;

    Color black = new Color(0,0,0);
    Color grey = new Color(128,128,128);
    boolean col = true;

    for(int i=0; i<square.length; i++)
    {
        for(int j=0; j<square[i].length; j++)
        {
            if(col)
                comp2d.setPaint(black);
            else
                comp2d.setPaint(grey);
            col = !col;
            square[i][j] = new Rectangle2D.Float(xOffSet+j*cellSize, i*cellSize, cellSize, cellSize);
            comp2d.fill(square[i][j]);
        }
    }

}

public static void main(String[] args)
{
    JFrame frame = new JFrame("Conway's Game Of Life");
    TextFrame life = new TextFrame();
    frame.add(life);
    frame.setSize(life.getHeight(), life.getWidth());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}
}

Solution

  • The reason for intervals is integer arithmetic. Change:

    int cellSize, xOffSet;
    

    to:

    float cellSize, xOffSet;
    

    Also, change:

    cellSize = (int)getHeight()/numOfCells;
    

    to:

    cellSize = getHeight()/(float)numOfCells;
    

    Some other side notes:

    • Do not change visibility of paintComponent, it is defined as protected.

    • Don't forget to add super.paintComponent(comp); in paintComponent()

    • Do not call setSize(), override panel's getPreferredSize() and pack() the frame. For example:

      public Dimension getPreferredSize(){return new Dimension(400, 400);}
      

      Then, add frame.pack(); before making the frame visible.

    • Try to make paintComponent as fast as possible for better performance and user experience. You can move some things out of it, leaving only painting logic.