使用计时器动画 JPanel(滑入) [英] animate JPanel (slide in) with timer
问题描述
我正在尝试使用我制作的此类从侧面滑入 JPanel:
I am trying to make a JPanel slide in from the side using this class i made:
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();
}
}
好吧,我不知道问题是什么.我尝试了很多不同的东西,但我似乎无法让它发挥作用.
Well, i dont know what the problem is. I've tried a lot of different things, but i doesn't seem like I can get it to work.
推荐答案
计时器应该在每个刻度上改变位置,直到它就位,相反,在每个刻度上,你正在运行一个 for-next 循环,它会阻塞 EDT 直到循环完成,从而阻止更新 UI
The timer should be changing the location on each tick, until it is in place, instead, on each tick, you're running through a for-next loop, which is blocking the EDT until the loop finishes, preventing from updating the 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 个父母做了,不要再说了……)
I should have added this in last night (1 year who didn't want to go to bed, 2 parents that did, say no more...)
动画是一个复杂的话题,尤其是当你开始研究变速时(这个例子是静态的).
Animation is complex topic, especially when you start looking at variable speed (the example is static).
与其重新发明轮子,不如认真考虑看看......
Instead of reinventing the wheel, you should seriously consider taking a look at...
- Timing Framework - This is base animation framework, that makes no assumptions about how you might like to use it.
- Trident - Similar to the Timing Framework, but also has support for Swing based components (via reflection) build in
- Universal Tween Engine
这篇关于使用计时器动画 JPanel(滑入)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!