2013-03-30 61 views
2

我試圖讓兩個盒子從JPanel的右上角移動到左下角。對於動畫,我使用的是Swing Timer和SwingUtilities.invokeLater()。問題是,當我點擊開始按鈕。它只會動畫和移動藍色框,而不是紅色框。JPanel中的擺動定時器和動畫

繼承人的代碼:

//import neccessary stuff 
public class Example extends JFrame { 
public static void main(String[] args) { 
    Example e = new Example(); 
    e.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    e.setSize(600, 565); 
    e.setVisible(true); 
}</code> 

private JButton startButton = new JButton("Start"); 

private JPanel theTable = new table(); 


public Example() { 
    add(startButton, BorderLayout.SOUTH); 
    add(theTable, BorderLayout.CENTER); 
    Handler handler = new Handler(); 
    startButton.addActionListener(handler); 
} 

public ArrayList<Integer> xPos, yPos; 
final int START_POSITION_X = 470; 
final int START_POSITION_Y = 10; 

final int[] END_POSITION_X = {70, 87}; 
final int END_POSITION_Y = 160; 

private class table extends JPanel { 

    public table() { 
     xPos = new ArrayList<Integer>(); 
     yPos = new ArrayList<Integer>(); 
     xPos.add(START_POSITION_X); //default position for box1 
     yPos.add(START_POSITION_Y); 
     xPos.add(START_POSITION_X); //default position for box2 
     yPos.add(START_POSITION_Y); 
    } 

    public void paintComponent(Graphics g) { 

     super.paintComponent(g); 
     this.setBackground(new Color(-16756217)); 
     g.setColor(Color.RED); 
     g.fillRect(xPos.get(1), yPos.get(1), 89, 129); 
     g.setColor(Color.BLUE); 
     g.fillRect(xPos.get(0), yPos.get(0), 89, 129); 

     if (isAnimating) { 
      animator.start(); 
     } else { 
      animator.stop(); 
      isAnimating = false; 
     } 
    } 
} 

private class Handler implements ActionListener { 
    public void actionPerformed(ActionEvent e) { 

     Runnable r1 = new Runnable() { 
      @Override 
      public void run() { 
       animateCard(0, END_POSITION_X[0], END_POSITION_Y); 
      } 
     }; 
     SwingUtilities.invokeLater(r1); 
     animateCard(1, END_POSITION_X[1], END_POSITION_Y); 
    } 
} 

public void animateCard(int card, int xDest, int yDest) { 
    cardID = card; 
    xDestination = xDest; 
    yDestination = yDest; 
    totalXDistance = Math.abs(xDestination - START_POSITION_X); 
    totalYDistance = Math.abs(yDestination - START_POSITION_Y); 
    animator.start(); 
} 
int cardID; 
int xDestination, yDestination, totalXDistance, totalYDistance; 
boolean isAnimating = false; 
Timer animator = new Timer(15, new ActionListener() { 
    int startVel = 20; 

    public void actionPerformed(ActionEvent e) { 
     double xRelDistance, xAbsDistance, xVel; 
     int xRealVel; 
     xAbsDistance = xDestination - xPos.get(cardID); 
     xRelDistance = xAbsDistance/totalXDistance; 
     xVel = startVel * xRelDistance; 

     double yRelDistance, yAbsDistance, yVel; 
     yAbsDistance = yDestination - yPos.get(cardID); 
     yRelDistance = yAbsDistance/totalYDistance; 
     yVel = startVel * yRelDistance; 

     if (xVel > 0) { 
      xRealVel = (int) java.lang.Math.ceil(xVel); 
     } else { 
      xRealVel = (int) java.lang.Math.floor(xVel); 

     } 
     xPos.set(cardID, xPos.get(cardID) + xRealVel); 
     int yRealVel; 
     if (xVel > 0) { 
      yRealVel = (int) java.lang.Math.ceil(yVel); 
      yPos.set(cardID, yPos.get(cardID) + yRealVel); 
     } else { 
      yRealVel = (int) java.lang.Math.floor(yVel); 

     } 
     yPos.set(cardID, yPos.get(cardID) + yRealVel); 

     if ((xPos.get(cardID) == xDestination) && (yPos.get(cardID) == yDestination)) { 
      isAnimating = false; 
     } else { 
      isAnimating = true; 
     } 
     repaint(); 
    } 
}); 

} 

回答

0

因此,所有在類級別聲明的那些變量的共享......您對animateCard第一個電話將設置它們,然後你到animateCard秒通話將要完全覆蓋以前的值。您需要將它們從類變量更改爲動畫的參數。

創建一個新類AnimationTask實現ActionListener並保存變量該類。

例如,

class AnimationTask implements ActionListener { 
    private int cardID; 
    private int xDest; 
    private int yDest; 
    private int totalXDistance; 
    private int totalYDistance; 
    public AnimationTask(int cardID, int xDest, int yDest) { 
     this.cardID = cardID; 
     this.xDest = xDest; 
     this.yDest = yDest; 
     this.totalXDistance = Math.abs(xDestination - START_POSITION_X); 
     this.totalYDistance = Math.abs(yDestination - START_POSITION_Y); 
    } 

    public void actionPerformed(ActionEvent e) { 
     // do your animation logic... 
    } 
} 

,並使用自定義類在您的 「動畫」

例如,

Timer animator = new Timer(15, new AnimationTask(cardId, xDest, yDest); 
+0

感謝您的快速回答,這解決了這個問題。動畫現在都在同一時間,這也是有效的。如果我想等到一個完成,然後讓另一個完成,我該怎麼做? – Griphold

0

animateCard(1, END_POSITION_X[1], END_POSITION_Y); 

您的run方法裏面:

public void run() { 
      animateCard(0, END_POSITION_X[0], END_POSITION_Y); 
     }