I am trying to create an function with an animation in java(swing). I want to create a "stack" of cards and then be able to draw one card from the stack using a method. The card i draw should then be "fliped" to reveal the front side.
This is working fine unless when I am trying to draw a new card using listeners.
I start the program by building the stack then drawing one card. Then I have a button that draws a new card(actionlistener). The animation does not show however i can see that the stack decreases by one card. I have 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 would be that it has something to do with threads or the EDT?
Here is the code(I have removed the use of the Scalr class since its 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 so that the animation is shown regardless if its called from the listener?
using timer would be the solution for you:) Example of a similar problem that guy had a similar problem, you can read the answers he received. good luck
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With