Question

I would like to re-paint a square after a mouse click but the re-paint method will be invoiked 10 times.

For example in the square is in x,y it will be repainted after a mouse click in:

  • x+1,y+1
  • x+2,y+2
  • x+3,y+3
  • ...
  • ...
  • x+10,y+10

I tried to loop the repaint method 10 times but the result was the final paint instead of the whole process.

public MyPanel() 
{

    setBorder(BorderFactory.createLineBorder(Color.black));

    addMouseListener(new MouseAdapter() 
    {
        public void mousePressed(MouseEvent e) 
        {   
            for(int i=0;i<10;i++)
                moveSquare(redSquare.getX(),redSquare.getY());
        }
    });

}
private void moveSquare(int x, int y) 
{
    final int CURR_X = redSquare .getX();
    final int CURR_Y = redSquare.getY();
    final int CURR_W = redSquare.getWidth();
    final int CURR_H = redSquare.getHeight();
    final int OFFSET = 1;

    // The square is moving, repaint background 
    // over the old square location. 
    repaint(CURR_X,CURR_Y,CURR_W+OFFSET,CURR_H+OFFSET);

    // Update coordinates.
    redSquare.setX(x+1);
    redSquare.setY(y+1);

    // Repaint the square at the new location.
    repaint(redSquare.getX(), redSquare.getY(), 
            redSquare.getWidth()+OFFSET, 
            redSquare.getHeight()+OFFSET);

}
Was it helpful?

Solution 3

The call to repaint will not immediately cause the component to be repainted. It only tells the rendering system: "Repaint this area as soon as possible". But the rendering system is busy with iterating through your for loop.

The reason is that the mousePressed method is executed by the same thread that is also responsible for repainting - namely by the Swing Event Dispatch Thread (EDT). So this thread is running through your for loop and triggering repaints, but only after it has finished the for loop it is able to actually execute the repaint - and then, only the last state will be visible.

The solution here should be to execute the movement in an own thread. The straightforward solution could look like this

public void mousePressed(MouseEvent e) 
{   
    moveInOwnThread();
}

private void moveInOwnThread()
{
    Thread t = new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            move();
        }
    });
    t.setDaemon(true);
    t.start();
}

private void move()
{
    for(int i=0;i<10;i++)
    {
        moveSquare(redSquare.getX(),redSquare.getY());

        try
        {
            Thread.sleep(20);
        }
        catch (InterruptedException e)
        {
            Thread.currentThread().interrupt();
            return;
        }
    }
}

But you should read something about concurrency in swing: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/

OTHER TIPS

If I understand correctly, you want to click somewhere, and have the square move there, but have the square have some type of moving animation towards that new location.

You're moving your square and repainting it too fast that it will seem as if the square has only moved from it's initial position to it's new final position. You can if you want, set x and y pixel velocities, and update the square's position in a loop that moves the square towards it's final spot you want it to based on how much time has elapsed between the last loop iteration times those x and y velocities.

Use a Swing Timer to schedule animation. Read the section from the Swing tutorial on How to Use Timers for more information.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top