JPanel中的Swing Timers和Animations [英] Swing Timers and Animations in JPanel

查看:72
本文介绍了JPanel中的Swing Timers和Animations的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Im trying to animate 2 boxes to go from the top right to the bottom left of a JPanel. For the animation I'm using a Swing Timer and SwingUtilities.invokeLater(). The problem is that when I click the start button. It only animates and moves the blue box, but not the red one.

下面是代码:

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

}


推荐答案

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

So all of those variable declared at the class level are shared... Your first call to animateCard will set them and then your second call to animateCard is going to completely overwrite the previous values. You need to change them from class variables to parameters of the animation.

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

Create a new class AnimationTask that implements ActionListener and save the variables in that class.

例如,

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...
    }
}

并在animator中使用该自定义类

and use that custom class in your "animator"

例如,

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

这篇关于JPanel中的Swing Timers和Animations的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆