0

i have the following code for animating a ball from top left corner towards the bottom right corner.

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class MainFrame{ 
    int i=0,j=0;
    JFrame frame = new JFrame();
    public void go(){   
         Animation anim = new Animation();
         anim.setBackground(Color.red);//Why color is not changing to red for the panel.
         frame.getContentPane().add(anim);
         frame.setVisible(true);
         frame.setSize(475,475);
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         for(i=0,j=0;i<frame.getHeight()&&j<frame.getWidth();++i,++j){
               anim.repaint();//Main problem is here,described below.
               try{
                   Thread.sleep(50);
               }
               catch(Exception ex){}
         }
    }
    public static void main(String[] args) {
         MainFrame mf = new MainFrame();
         mf.go();
    }

    class Animation extends JPanel{
         public void paintComponent(Graphics g){
             Graphics2D g2d = (Graphics2D)g;
             g.fillOval(i,j,25,25);
         }
    }
}

Questions

  1. When i do anim.repaint() inside the method go i don't get the ball animating from top left corner to bottom right corner but it gets smeared down the path.But if i replace it with frame.repaint() i get the desired result that is a moving ball.So what is the difference between these two calls to repaint?
  2. Why the color of panel is not changing after anim.setBackground(Color.red); in go method?
  3. If you run this programe you will find that the ball is not exactly going at the bottom edge,so how can i acheive that?
mKorbel
  • 109,525
  • 20
  • 134
  • 319
OldSchool
  • 2,123
  • 4
  • 23
  • 45
  • _Don't_ sleep on the EDT; _do_ see [*Concurrency in Swing*](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) and [*How to Use Swing Timers*](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html); a complete example is examined in this possible [duplicate](http://stackoverflow.com/q/9849950/230513). – trashgod Jul 23 '14 at 19:40
  • `Don't sleep on the EDT` - that is always good advice but the looping code is not actually executing on the EDT because you are NOT creating your GUI correctly. All GUI component SHOULD be created on the EDT. This is done by using the `SwingUtilities.invokeLater()` method as demonstrated in the tutorial linked above. However, once you do that you will have painting problems because you will be causing the EDT to sleep which means it won't be able to paint the moving ball until the loop finishes. So you will need to follow the advice to use the Timer. – camickr Jul 23 '14 at 20:27
  • @camickr makes a crucial observation: you're sleeping on the [initial thread](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html) _after_ the call to `setVisible()`; the EDT will begin running asynchronously, and the result will be unpredictable. – trashgod Jul 23 '14 at 22:13

1 Answers1

3

);//Why color is not changing to red for the panel

You should always invoke super.paintComponent(g) when you override the paintComponent(...) method. The default code is responsible for painting the background.

but it gets smeared down the path

Same answer as above. You need the background to be painted so that all the old paintings are removed.

the ball is not exactly going at the bottom edge

If you mean the ball is not on an exact diagonal on the panel, that is because you set the size of the frame manually and you did not account for the size of the titlebar and borders. If you want the panel to be (475, 475) then override the getPreferredSize() method of the panel to return that dimension. Then in your code you replace the frame.setSize() with frame.pack().

camickr
  • 321,443
  • 19
  • 166
  • 288