I'm creating an animated slide transition in Java, and it is choppy on my current model MacBook Pro and on my year-old iMac, on Java 6, 7, and 8.
What can I do to make this animation appear smoother to the user on Mac OS X?
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ScratchSpace {
public static void main(String[] args) {
AnimatedPanel panel = new AnimatedPanel();
JFrame frame = new JFrame();
frame.setContentPane(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
panel.animate();
}
public static class AnimatedPanel extends JPanel {
private float progress = 0.0f; // a number between 0.0 and 1.0
public AnimatedPanel() {
setPreferredSize(new Dimension(800, 600));
setOpaque(true);
}
public void animate() {
final int animationTime = 1000;
int framesPerSecond = 30;
int delay = 1000 / framesPerSecond;
final long start = System.currentTimeMillis();
final Timer timer = new Timer(delay, null);
timer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final long now = System.currentTimeMillis();
final long elapsed = now - start;
progress = (float) elapsed / animationTime;
repaint();
if (elapsed >= animationTime) {
timer.stop();
}
}
});
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
int width = getWidth();
int progressWidth = (int) (width * progress);
g2d.setColor(Color.BLUE);
g2d.fillRect(0, 0, progressWidth, getHeight());
g2d.setColor(Color.RED);
g2d.fillRect(progressWidth, 0, width-progressWidth, getHeight());
}
}
}
A lot depends on what it is you ultimately want to achieve.
Remember, animation is the illusion of movement...
I changed
framesPerSecond
to60
which seems to have helped.repaint(Rectangle)
passing in only that area which has changed.The other problem is your animation has a large area to cover in a very short period of time. Increasing the amount of time will also make it smoother (or reducing the width and/or height)
Alternativly, you could generate you own backing buffer and update it...
The major problem you have is basically the area you are trying to paint is to large for the time you want to paint it.
Another Alternatively
You could create a
BufferedImage
that represents the progress bar and move as the progress updates. This update creates a compatible buffered image, which should make it faster to renderer