This discussion is archived
1 2 3 Previous Next 30 Replies Latest reply: Dec 28, 2010 7:34 PM by DarrylBurke RSS

force the repaint of a JPanel

843853 Newbie
Currently Being Moderated
Hi all,

I want to create a little animation by calling an animate() function in a JPanel but repaint() doesn't force the UI refresh! I've tried to use paintImmediately() as well but it was not working better!

Here a simplified version of my code:
class MyPanel extends JPanel{
     
     int movX,movY;
     Image movImage;
     
     MyPanel(){          
          setSize(500, 500);      
     }
     
     void animate(int fromCell, int toCell){
     
                   movImage = Toolkit.getDefaultToolkit().getImage("image.gif")
          
          for (int i=100; i<400; i++){
               movX = i;
               movY = i;
               repaint();   //--- repaint() here does not work!!!
          }
          
          movImage = null;
     }
     
     public void paintComponent(Graphics g){
          
          //--- draw background
          
          g.setColor(Color.white);
          g.fillRect( 0, 0, 500, 500);
          
          //--- draw image

          if (movImage!=null) g.drawImage(movImage, movX, movY, this);
     }
     
     public void update(Graphics g){
          paint(g);
     }
     
}
Any ideas why?
Thanks very much for your help.
Denis
  • 1. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    try this:
    Graphics g = getGraphics();
    if (g != null) paintComponent(g);
    else repaint();
  • 2. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    It is not recommended to call the paint method directly...

    public void repaint()

    Repaints this component.
    If this component is a lightweight component, this method causes a call to this component's paint method as soon as possible. Otherwise, this method causes a call to this component's update method as soon as possible.

    In other words, it only get painted if there is time to... try this:
    for (...)
    {
         ...
         repaint();
         try
         {
              Thread.sleep(20); // sleep for 20 milliseconds
         }
         catch (Exception e)
         {
              e.printStackTrace();
         }
    }
  • 3. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    It is not recommended to call the paint method
    directly...
    says who? active rendering is a common technique used in games. Unless you're referring to it being unsafe in swing components... I don't know much about swing. I do know swing isn't reccomended for animation-based games though...
  • 4. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    It is not recommended to call the paint method
    directly...
    says who? active rendering is a common technique used
    in games. Unless you're referring to it being unsafe
    in swing components... I don't know much about swing.
    I do know swing isn't reccomended for animation-based
    games though...
    I could have sworn I read it somewhere ;P
  • 5. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    I could have sworn I read it somewhere ;P
    Here it is http://java.sun.com/products/jfc/tsc/articles/painting/index.html#swing_summary

    Swing Painting Guidelines
    Swing programs should understand these guidelines when writing paint code:

    For Swing components, paint() is always invoked as a result of both system-triggered and app-triggered paint requests;update() is never invoked on Swing components.

    Programs may trigger a future call to paint() by invoking repaint(), but shouldn't call paint() directly.

    ...
  • 6. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    Thanks for your replies guys but none of them worked successfully!

    I have also tried (unsuccessfully) this one:
    class MyPanel extends JPanel{
       
            int movX,movY;
      Image movImage;
     
            MyPanel(){              
                    setSize(500, 500);      
            }
           
            void animate(int fromCell, int toCell){
     
                       movImage = Toolkit.getDefaultToolkit().getImage("image.gif")
             
                    for (int i=100; i<400; i++){
                        movX = i;
                           movY = i;
                           repaint();   //--- repaint() here does not work!!!
                  }
                   
                    movImage = null;
            }
           
            public void paintComponent(Graphics g){
             
                    //--- draw background
               
                    g.setColor(Color.white);
                    g.fillRect( 0, 0, 500, 500);
                
                    //--- draw image
    
                    if (movImage!=null) g.drawImage(movImage, movX, movY, this);
    try{
                   Thread.sleep(20); // sleep for 20 milliseconds
      } catch (Exception e){
                   e.printStackTrace();
        }
    
        }
           
            public void update(Graphics g){
             paint(g);
           }
           
    }
    The only interesting result so far is for the last iteration, the image.gif is displayed once with coordinates (400,400). All the other iterations are just skipped!

    In the real code, MyPanel implements MouseListener, MouseMotionListener as well and from the mouseDragged(MouseEvent e) function I can call repaint() successfully.

    ???
    Denis
  • 7. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    I've done new tests.
    This code
    Graphics g = getGraphics();
    if (g != null) paintComponent(g);
    else repaint();
    is working fine with a jvm 1.3.1, not is not ok with a jvm 1.4.1

    ???
    Thanks very much for your help
  • 8. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    Hi all,

    I have done more tests and here the results. If I use:

    repaint()
    - jvm 1.3.1: no animation,
    - jvm 1.4.2: no animation

    repaint() + Thread.sleep(20) (or whatever value instead of 20)
    - jvm 1.3.1: no animation,
    - jvm 1.4.2: no animation

    paintImmediately()
    - jvm 1.3.1: animation (with flickering),
    - jvm 1.4.2: sometimes I got the last image displayed!

    paintComponent(g)
    - jvm 1.3.1: animation (with flickering),
    - jvm 1.4.2: sometimes I got the last image displayed!


    Therefore I am asking myself a few questions:

    - is repaint() definitely a bad function for animations?
    - is jvm 1.4.2 a bad jvm for animations?
    - or am I simply a bad developper? ;-)

    Any help would be really appreciated.
    Thanks
    Denis
  • 9. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    using swing for animation, that is brave!!

    i will be happy if i can just get the progress bar on my form to work properly for pete's sake. swing. grrrrr

    i finally got it to work by using paintImmediately at the end of the loop, but only if I call JFrame.show() immediately before the loop. Thank you for posting your results Denis, this was invaluable to me.

    my code (FINALLY working) (sun JVM 1.4.1.05):

    // initialize progress bar prbStatus
    fraMain.show();

    for (i = 0; ai.nextRecord(); i++) {
         db.updateDb(ai.getRecord());
         prbStatus.setValue(i);

    // force JPanel to repaint
         pnlMain.paintImmediately(0,0,
         pnlMain.getWidth(),
         pnlMain.getHeight());
    }
  • 10. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    >
    The only interesting result so far is for the last
    iteration, the image.gif is displayed once with
    coordinates (400,400). All the other iterations are
    just skipped!

    In the real code, MyPanel implements MouseListener,
    MouseMotionListener as well and from the
    mouseDragged(MouseEvent e) function I can call
    repaint() successfully.
    The repaint runs on the EventDispatcher Thread, which also handles the mouse Events - maybe that slows down your animation..

    also you have to call super.paintComponent(g) in the overridden paintComponent() method.
  • 11. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    call Thread.sleep(ms) after you call repaint.
    ...
    
    repaint();
    
    try
    {
         Thread.sleep(ms);
    }
    catch (Exception e)
    {
         e.printStackTrace();
    }
    
    ...
  • 12. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    Call

    revalidate();

  • 13. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    call Thread.sleep(ms) after you call repaint.
    Thread.sleep cannot provide absolute assurance that a subsequent repaint() will be successfully executed (a point that is actually implied by the inclusion of the argument "ms"in this recommendation).

  • 14. Re: force the repaint of a JPanel
    843853 Newbie
    Currently Being Moderated
    sorry, just noticed the attention getting "after".
1 2 3 Previous Next