2014-06-19 120 views
4

我想用java(swing)中的動畫創建函數。我想創建一個「堆棧」卡,然後能夠使用方法從堆棧中抽取一張卡。然後我畫的牌應該「翻轉」以露出正面。Swing java動畫只在未從監聽器調用時才起作用

這工作正常,除非當我試圖使用偵聽器繪製一張新卡。

我通過構建堆棧然後繪製一張卡來啓動程序。然後我有一個繪製新卡的按鈕(actionlistener)。但是,我看不到動畫顯示堆疊減少一張卡片。我試圖創建一個gif來展示問題。

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

我最好的猜測是,它是與線程或EDT?

下面是代碼(因爲它並不重要我已刪除了使用Scalr類):

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(); 
} 
} 

問題=什麼可以做這樣不管是顯示動畫如果從被叫聽衆?

+3

我相信你已經在這個主題上搜索過,我確定你已經閱讀不要在Swing事件線程上調用'Thread.sleep(...)',請嘗試我確信你在搜索中找到了一些建議,包括使用Swing Timer。 –

+0

@HovercraftFullOfEels你是對的,使用'Thread.sleep'不好。但即使所有的Thread.sleep被移除,它仍然不起作用。 – Ragnarsson

+1

再次嘗試使用計時器。您需要用定時器替換長時間運行的循環,因爲它們與EDT相關。 –

回答

0

使用計時器將是你的解決方案:) Example of a similar problem那傢伙有類似的問題,你可以閱讀他收到的答案。祝你好運