I want to add squares onto a jpanel one at a time after a delay . My program works fine until I tried to change the background color with setBackgound(). It didn't change. I worked out I have to call super.paintComponent(gr) in my paintComponent method. But when I do this and call repaint(), only the current square is displayed. The previous one's have disappeared. I know it is because repaint is displaying a whole new panel each time but why does it work when I don't call super.paintComponent(). Here is a simplified version of ghe code

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

public class Squares extends JFrame{
   aPanel ap = new aPanel();   
   SlowDown sd = new SlowDown(); //slows down program by given number of milliseconds 

   public Squares(){
      super("COLOURED SQUARES");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      add(ap);
      ap.setPreferredSize(new Dimension(300, 300));
      pack();
      setVisible(true);
      addSquares();
  }

   private void addSquares(){
      sd.slowDown(500);
      ap.changeSquare( 100 , 100 , 255 , 0 , 0);
      ap.repaint();

      sd.slowDown(500);
      ap.changeSquare( 200 , 200 , 0 , 0 , 255);
      ap.repaint();     
   }



  public static void main(String[] arguments) {
     Squares sq  = new Squares();
  }


class aPanel extends JPanel{

   private int x = 0;
   private int y = 0;
   private int r = 0;
   private int g = 0;
   private int b = 0;   

   public void paintComponent(Graphics gr) {
      //super.paintComponent(gr);
      Color theColor = new Color (r, g, b);
      gr.setColor(theColor);
      gr.fillRect(x,y,30,30); 
 }
   void changeSquare(int i , int j, int rd , int gr , int bl){
       x = i;
       y = j;
       r = rd;
       g = gr;
       b = bl;
   }
}

class SlowDown{
  void slowDown(long delay){
     long t = System.currentTimeMillis();
     long startTime = t;
     while(t < startTime + delay){
      t = System.currentTimeMillis();           
   }
  }
}
}

The reason the old rectangle dissapears is because the super.paintComponent() clears the foreground with the background color, it's the same as calling gr.setColor(getBackground()); gr.fillRect(0,0,getWidth(),getHeight()); in the beginning of your paintComponent() method.

Every time you call super.paintComponent() it clears the display. when you don't call super.paintComponnt() it never has a chance to use the background color, but it also never clears the old rectangle off the screen from the last call, so you see more than one even though you only ever draw once per repaint() call.

To have both you could reset the background color manually before you started drawing the rectangles: NOTE: untested may not be correct but should work

private void addSquares(){
    Graphics g = ap.getGraphics();
    g.setColor(ap.getBackground());
    g.fillRect(0,0,ap.getWidth(),ap.getHeight());
    g.dispose();
    sd.slowDown(500);
    ap.changeSquare( 100 , 100 , 255 , 0 , 0);
    ap.repaint();
    sd.slowDown(500);   
    ap.changeSquare( 200 , 200 , 0 , 0 , 255);
    ap.repaint();
}

or you could actually use multiple rectangles.

EDIT: also instead of the while loop that checks milliseconds it would probably be better to use a simple:

try{
    Thread.sleep(milliseconds);
} catch(InterruptedException e){}

because the while loop will not let other processes get CPU time while sleep will.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.