当前位置: 首页 > 面试题库 >

JPanel中的Swing计时器和动画

章越
2023-03-14
问题内容

我正在尝试为JPanel的右上角到左下角的2个框设置动画。对于动画,我使用了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();
    }
});

}

问题答案:

因此,所有在类级别声明的变量都是共享的。您的第一个调用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);


 类似资料:
  • 问题内容: 我正在尝试使用我制作的此类从侧面制作JPanel幻灯片: 好吧,我不知道问题是什么。我已经尝试了很多不同的方法,但是我似乎无法使其正常工作。 问题答案: 计时器应该在每个刻度上更改其位置,直到它就位为止,相反,您正在运行一个for-next循环,该循环阻止EDT直到循环结束,从而阻止更新UI 更新示例 例如… 更新资料 我本该在昨晚添加的(1岁不想睡觉的人,2个父母做了,不想再说了……

  • 问题内容: 我将再次发布此问题,以使其更加精确,希望我能得到一些帮助,因为这使我发疯。我正在开发一个 最多可容纳6名玩家的棋盘游戏,每个玩家都有一个不同的彩色棋子。我将以下图像加载到BufferedImage数组中,将其视为 精灵: 在此处输入图片说明 这是相对代码,将每个有色模具的每个面放在BufferedImage [] 中的某个位置: 然后,每个玩家根据自己的颜色,还将具有以下矩阵,该矩阵包

  • 问题内容: 我是Java图形设计的新手,如果可能的话,我希望您能通过一个简单的示例帮助我,以帮助我了解JFrames,Timer,SwingControllers以及所有这些东西的基本功能。您将如何实现以下情况: 我们有一个内部带有JPanel的JFrame。执行开始时,JPanel为白色,但我们希望它每两秒钟更改一次其颜色: 最初,我在setBackgroud()方法之间使用了线程对象的slee

  • 我在玩Java Swing,当谈到JPanel和JComponent时,我真的很困惑。根据CoreJava第一卷(cay horstmann): 有些程序员宁愿扩展JPanel类,而不是扩展JComponent。JPanel是一个可以包含其他组件的容器,但也可以在其上涂漆。只有一个区别。面板是不透明的,这意味着它负责绘制其边界内的所有像素。实现这一点的最简单方法是调用super,用背景色绘制面板。

  • 问题内容: 我正在尝试在Java Swing中构建MVC应用程序。我有一个包含四个JComboBox的JPanel,并且此JPanel嵌入到父JPanel中。父级JPanel除了子级JPanel之外,还具有其他控件。 每当我更改JComboBoxes的值时,子级JPanel的模型就会正确更新(它基本上是一个日期选择器,每个年,月,日,日和小时中都有一个组合框)。我无法弄清楚的是,每当更改了一个JC