【问题标题】:Swing Timers and Animations in JPanelJPanel 中的摆动定时器和动画
【发布时间】:2013-03-30 22:42:35
【问题描述】:

我正在尝试为 2 个框设置动画,使其从 JPanel 的右上角到左下角。对于动画,我使用的是 Swing Timer 和 SwingUtilities.invokeLater()。问题是当我单击开始按钮时。它只会动画和移动蓝色框,而不是红色框。

代码如下:

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

}

【问题讨论】:

    标签: java swing animation timer


    【解决方案1】:

    所以在类级别声明的所有这些变量都是共享的...您对animateCard 的第一次调用将设置它们,然后您对animateCard 的第二次调用将完全覆盖以前的值。您需要将它们从类变量更改为动画的参数。

    创建一个实现ActionListener 的新类AnimationTask,并将变量保存在该类中。

    例如,

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

    【讨论】:

    • 感谢您的快速回答,这解决了它。动画现在同时进行,这也有效。如果我想等到一个完成后再让另一个完成,我该怎么做?
    【解决方案2】:

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

    在你的运行方法中:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      • 1970-01-01
      相关资源
      最近更新 更多