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

使用计时器为JPanel动画(插入)

时旭东
2023-03-14
问题内容

我正在尝试使用我制作的此类从侧面制作JPanel幻灯片:

public class AnimationClass {

    private int i;
    private int y;
    private JPanel panel;
    private int xTo;
    private Timer timer;
    private int xFrom;

    synchronized void slidePanelInFromRight(JPanel panelInput, int xFromInput, int xToInput, int yInput, int width, int height) {
        this.panel = panelInput;
        this.xFrom = xFromInput;
        this.xTo = xToInput;
        this.y = yInput;

            panel.setSize(width, height);

            timer = new Timer(0, new ActionListener() {
                public void actionPerformed(ActionEvent ae) {

                    for (int i = xFrom; i > xTo; i--) {
                        panel.setLocation(i, y);
                        panel.repaint();
                        i--;

                        timer.stop();
                        timer.setDelay(100);

                        if (i >= xTo) {
                            timer.stop();
                        }
                    }
                    timer.stop();

                }
            });
            timer.start();

    }

}

好吧,我不知道问题是什么。我已经尝试了很多不同的方法,但是我似乎无法使其正常工作。


问题答案:

计时器应该在每个刻度上更改其位置,直到它就位为止,相反,您正在运行一个for-next循环,该循环阻止EDT直到循环结束,从而阻止更新UI

更新示例

例如…

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestAnimatedPane {

    public static void main(String[] args) {
        new TestAnimatedPane();
    }

    public TestAnimatedPane() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JPanel panel;

        public TestPane() {
            setLayout(null);
            panel = new JPanel();
            panel.setBackground(Color.RED);
            add(panel);
            Dimension size = getPreferredSize();

            Rectangle from = new Rectangle(size.width, (size.height - 50) / 2, 50, 50);
            Rectangle to = new Rectangle((size.width - 50) / 2, (size.height - 50) / 2, 50, 50);

            Animate animate = new Animate(panel, from, to);
            animate.start();

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public static class Animate {

        public static final int RUN_TIME = 2000;

        private JPanel panel;
        private Rectangle from;
        private Rectangle to;

        private long startTime;

        public Animate(JPanel panel, Rectangle from, Rectangle to) {
            this.panel = panel;
            this.from = from;
            this.to = to;
        }

        public void start() {
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    long duration = System.currentTimeMillis() - startTime;
                    double progress = (double)duration / (double)RUN_TIME;
                    if (progress > 1f) {
                        progress = 1f;
                        ((Timer)e.getSource()).stop();
                    }
                    Rectangle target = calculateProgress(from, to, progress);
                    panel.setBounds(target);
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.setInitialDelay(0);
            startTime = System.currentTimeMillis();
            timer.start();
        }

    }

    public static Rectangle calculateProgress(Rectangle startBounds, Rectangle targetBounds, double progress) {

        Rectangle bounds = new Rectangle();

        if (startBounds != null && targetBounds != null) {

            bounds.setLocation(calculateProgress(startBounds.getLocation(), targetBounds.getLocation(), progress));
            bounds.setSize(calculateProgress(startBounds.getSize(), targetBounds.getSize(), progress));

        }

        return bounds;

    }

    public static Point calculateProgress(Point startPoint, Point targetPoint, double progress) {

        Point point = new Point();

        if (startPoint != null && targetPoint != null) {

            point.x = calculateProgress(startPoint.x, targetPoint.x, progress);
            point.y = calculateProgress(startPoint.y, targetPoint.y, progress);

        }

        return point;

    }

    public static int calculateProgress(int startValue, int endValue, double fraction) {

        int value = 0;
        int distance = endValue - startValue;
        value = (int)Math.round((double)distance * fraction);
        value += startValue;

        return value;

    }

    public static Dimension calculateProgress(Dimension startSize, Dimension targetSize, double progress) {

        Dimension size = new Dimension();

        if (startSize != null && targetSize != null) {

            size.width = calculateProgress(startSize.width, targetSize.width, progress);
            size.height = calculateProgress(startSize.height, targetSize.height, progress);

        }

        return size;

    }
}

更新资料

我本该在昨晚添加的(1岁不想睡觉的人,2个父母做了,不想再说了……)

动画是一个复杂的主题,尤其是当您开始以可变速度观看时(示例是静态的)。

与其重新发明轮子,不如认真考虑一下…

  • 时序框架 -这是基本的动画框架,它不假设您可能会喜欢如何使用它。
  • Trident-与Timing Framework类似,但也支持内置的基于Swing的组件(通过反射)
  • 通用补间引擎


 类似资料:
  • 问题内容: 我正在尝试为JPanel的右上角到左下角的2个框设置动画。对于动画,我使用了Swing Timer和。问题是当我单击开始按钮时。它仅设置动画并移动蓝色框,而不移动红色框。 这是代码: 问题答案: 因此,所有在类级别声明的变量都是共享的。您的第一个调用将设置它们,然后第二个调用将完全覆盖以前的值。您需要将它们从类变量更改为动画的参数。 创建一个新类,该类实现并保存该类中的变量。 例如,

  • 问题内容: 有人可以教我如何使用a 来达到以下目的: 当我单击鼠标时,我需要一个开始动画的多边形(例如旋转等简单动画);当我再次单击时停止动画。 我对理解工作方式没有任何问题,但对于实际的动画来说,没有任何问题。我尝试在方法中用while块模拟动画,在该方法中我将绘制,擦除和重绘多边形(例如,模拟旋转),但是在while内,applet不会监听点击。它只会在片刻之后收听。单击鼠标时,我需要摆动计时

  • 我在Swing和设置角色动画方面有一些问题,我有一个带有关键侦听器的JFrame,当用户点击时,它在这里调用我的JPanel方法 这个动画我的角色,但这么快,我们可以看到一个东西,我怎么才能看到动画?

  • 我想用Angular(Angular CLI:11.2.2,Node:14.16.0,OS:win32 x64)使用Counter-Up插件(Counter-Up v2)的动画数字计数,但我有问题使它工作。 已安装[npm install Counterup2--Save] [从“counterup2”导入{counterUp};]在app.ts.module中导入-使用信息:声明了“counte

  • 我最近读了一个关于JAVAFX的课程,我想制作一个应用程序来吸收我所学到的东西。我想做一个2D游戏,其中一个球是通过抛物线的方式动画。我对这两个对象使用和。我必须承认,我不知道到底是如何工作的,我的问题是我想让动画停止时,球到达窗口的底部。 我想用两种方法: null

  • 如何像这样创建 在问答游戏中,每一关,这个都会倒计时时间,选择答案越快,得分越高。因此,第一件事是如何获得这个上的时间。