1

At the beginning I'd like to stress, that I'm quite new to Java and I always try to find the answer for my questions myself, but sometimes it happens that I reach the dead-end and that's why I'd like to ask you if you have an idea for that.

I try to make a card game. I would like to do a quite simply thing (in my opinion) that is, move a JLabel with an image of a card back from one point to another inside a JPanel that is parent to it, in a serie of moves with the delay of 40ms to create an "animation" of dealing the card.

However as I try to do it, I get duplications of the card despite of the fact that I refresh the parent JPanel. I've been searching for an answer how to do it for a long time until now and nothing worked for me. I tried to refresh the JLabel with the card itself, its parent JPanel too, but without any effects.

The only partial solution was to repaint the JPanel, that is a parent to this JPanel with JLabel, but it caused flickering of my whole GUI which is not acceptable. Only then, there was no duplications like this presented in the image I enclose here.

Note: I use absolute layout, however I'm aware of the fact how unprofessional it is. It's just because I don't know how to comply with the rest of my layout using another manager.

I'd be very grateful for any hints or solutions you may have for me.

Image presenting what I would like to achieve

https://i.stack.imgur.com/7JvRz.jpg

Image presenting the current situation

https://i.stack.imgur.com/mSa4r.jpg

public void moveCard() 
{
// move the card to x = 0 (its destination) inside the parent panel 
while (movedCard.getX() != 0)
    {
    // try to reach x = 0
    // as the starting x cannot be divided through 20 it must subtract 21 once at the end
    if (movedCard.getX() == 21)
        {
        movedCard.setLocation(movedCard.getX() - 21, movedCard.getY());
        }
        else
        {
        movedCard.setLocation(movedCard.getX() - 20, movedCard.getY());
        }
        // repaint the panel that the card is drawn on
        movedCard.getParent().paintComponents(movedCard.getParent().getGraphics());

        // wait until the card is moved for the next time  
        try
            {
                Thread.sleep(40);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        // set the location of the card to default
        movedCard.setLocation(341, movedCard.getY());
    }
}
camickr
  • 321,443
  • 19
  • 166
  • 288
Bloodlex
  • 447
  • 2
  • 6
  • 16
  • 2
    Swing GUIs and `Thread.sleep` do not mix. That's what [Swing Timers](https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html) are for. – TNT Jan 31 '16 at 00:34
  • Take a look [here](http://stackoverflow.com/questions/4392722/how-to-repaint-a-jpanel-after-have-drawn-on-it) and [here](http://stackoverflow.com/questions/9510125/difference-between-validate-revalidate-and-invalidate-in-swing-gui). It might be useful. And also, as @TNT suggested having `Thread.Sleep` placed there is not such a good idea. – Andy Jan 31 '16 at 00:37
  • 2
    Don't use getGraphics(). Don't invoke any painting method (ie. paintComponents) directly. The setLocation() should cause the component to repaint itself at the new location. – camickr Jan 31 '16 at 00:42
  • `I use absolute layout,` - well a null layout (maybe your IDE calls it AbsoluteLayout) will be required to animate the moving of a card. However, you may want to consider designing the main GUI using layout managers. Then to deal a card you could use a GlassPane and have the card animate over the glass pane from the location of the card deck to its final position. – camickr Jan 31 '16 at 00:48
  • @TNT Thank you very much for that. Now I'm using Swing Timer and it works great, but the problem now is, that I'd like the program to carry on **after** the timer finished its work, but now it seems to be doing everything at the same time. How can I make the Event Dispatch Thread I suppose wait for the timer to finish? – Bloodlex Jan 31 '16 at 04:09
  • @camickr Yes, now it works great with only setLocation() and without repaint. I will take it into consideration to avoid null layout (for Eclipse its absolute layout you're right :) ) because I know it has a lot of benefits. Thanks for the tip with a GlassPane. – Bloodlex Jan 31 '16 at 04:13

0 Answers0