Swing java animation only works when not called from a listener

I am trying to create a function with animation in java (swing). I want to create a "stack" of cards, and then I can extract one card from the stack using the method. Then the card I draw should be “flipped” to open the front side.

This works great if I'm not trying to draw a new map using listeners.

I run the program by creating a stack and then draw a single card. Then I have a button that draws a new map (actionlistener). The animation does not show, however, I see that the stack is reduced by one card. I tried to create a gif to show the problem.

Gif file showing the problem http://people.dsv.su.se/~chra4852/gif.gif

My best guess is that it has something to do with threads or EDT?

Here is the code (I removed the use of the Scalr class, since it is not important):

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.*;
// import org.imgscalr.Scalr; Removed for Stackoverflow

public class Test extends JFrame{

public static JPanel cardPanel = new JPanel();
public static JLayeredPane layerPane = new JLayeredPane();
private final CardFlipp cardFlipp;


Test() {
    cardFlipp = new CardFlipp();
    this.setLayout(new BorderLayout());
    layerPane.setPreferredSize(new Dimension(700, 300));
    add(cardPanel, BorderLayout.CENTER);
    JButton newJButton = new JButton("New card");
    newJButton.addActionListener(new drawNewCardListener());
    add(newJButton, BorderLayout.SOUTH);
    setSize(800,400);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setVisible(true);
    Point pos = new Point(10,30);
    cardFlipp.createCardFlipp(30, pos, layerPane, cardPanel);
    System.out.println("Now running on thread " + Thread.currentThread());
    try {
        Thread.sleep(3000);
    } catch (InterruptedException ex) {
        Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
    }
    cardFlipp.displayCard("http://imgi.se/image.php?di=IYW9");
}

public static void main(String[] args){
    new Test();
}

    class drawNewCardListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent ae) {
        System.out.println("Now running on thread " + Thread.currentThread());
        cardFlipp.displayCard("http://imgi.se/image.php?di=IYW9");
    }
    }
}


class CardFlipp extends JPanel{

private Point origin;
private BufferedImage icon;
private JLayeredPane lPane;
private JPanel jPanel;
private int lastCardDisplayedId = 0;

public void createCardFlipp(int amount, Point pos, JLayeredPane lPaneRef, JPanel jPanelRef) {
    origin = pos;
    setIcon("http://imgi.se/image.php?di=HPCJ");
    lPane = lPaneRef;
    jPanel = jPanelRef;
    for(int i = amount; i > 0; i--) {
        origin.x += 3;
        lPane.add(new Card(origin, icon, i), new Integer(amount-i));
        jPanel.add(lPane);
        lPane.revalidate();
        lPane.repaint();
        try {
            Thread.sleep(80);
        } catch (InterruptedException ex) {
            Logger.getLogger(CardFlipp.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

public void displayCard(String fileUrl) {
    Card c = (Card) lPane.getComponent(0);
    if(lastCardDisplayedId == 0) {
        origin = new Point(c.getBounds().x + 370, c.getBounds().y);
    }
    int cardId = c.getId();
    setIcon(fileUrl);
    c.flippCardRight(lastCardDisplayedId);
    lPane.remove(c);
    if(lastCardDisplayedId != 0) {
        for(int i = 0; i < lPane.getComponentCount(); i++) {
            c = (Card) lPane.getComponent(i);
            if(c.getId() == lastCardDisplayedId) {
                lPane.remove(c);
                break;
            }
        }
    }
    lPane.repaint();
    lPane.add(new Card(origin, icon, cardId), new Integer(0));
    jPanel.add(lPane);
    lastCardDisplayedId = cardId;
}

private void setIcon(String urlPath) {
    try {
        URL url = new URL(urlPath);
        icon = ImageIO.read(url);
    } catch (IOException e) {
        System.err.println(e);
        System.exit(-1);
        icon = null;
    }
}
}

class Card extends JComponent {

private BufferedImage buffImg;
private ImageIcon iconImg;
private final int id;

public Card(Point origin, BufferedImage img, int count) {
    buffImg = img;
    iconImg = new ImageIcon(buffImg);
    setBounds(origin.x,origin.y,iconImg.getIconWidth(),iconImg.getIconHeight());
    this.id = count;
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawImage(iconImg.getImage(), 0, 0, this);
}

public void flippCardRight(int count) {
    int x = count * 3;
    int newPosX = getBounds().x + iconImg.getIconWidth() + 20;

    while(getBounds().x < newPosX + x) {
        setBounds(getBounds().x+5,getBounds().y,iconImg.getIconWidth(),iconImg.getIconHeight());
        wait10MiliSec();
    }

    // Removed to not need the scalr class
    //int minimize = 10;
    //while(iconImg.getIconWidth() > minimize) {
        //buffImg = Scalr.resize(buffImg, Scalr.Method.SPEED, Scalr.Mode.FIT_EXACT, //iconImg.getIconWidth()-minimize, iconImg.getIconHeight(), Scalr.OP_ANTIALIAS);
        //iconImg = new ImageIcon(buffImg);
        //setBounds(getBounds().x+minimize-1,getBounds().y,iconImg.getIconWidth(),iconImg.getIconHeight());
        //wait10MiliSec();
    //}
}

private void wait10MiliSec() {
    try {
        Thread.sleep(10);
    } catch (InterruptedException ex) {
        Logger.getLogger(Card.class.getName()).log(Level.SEVERE, null, ex);
    }
}

public int getId() {
    return this.id;
}

public int getImgWidth() {
    return iconImg.getIconWidth();
}
}

Question = What can be done to make the animation display regardless of whether it was called from the listener?

+4
source share
1 answer

using a timer would be a solution for you :) An example of a similar problem is that the guy had a similar problem, you can read the answers he received. good luck

0
source

Source: https://habr.com/ru/post/1545229/


All Articles