Java – use timer to animate JPanel (slide)
I'm trying to make JPanel slides 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 don't know what the problem is I've tried many different things, but I can't seem to make it work
Solution
The timer should change the position of each tick until it is in place, not at each tick. You are running a for next loop, which prevents EDT from updating the UI until the end of the loop
Update with examples
For example
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,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;
}
}
to update
I should have added this last night (1 year without going to bed, 2 parents, no more...)
Animation is a complex topic, especially when you start looking at the transmission (the example is static)
You should seriously consider taking a look at... Rather than reinventing the wheel
>Timing framework – this is the basic animation framework and makes no assumptions about how you use it. > Trident – similar to the timing framework, but also supports swing based component (through reflection) building > Universal tween engine
