I have recently started Java and wondered if it was possible to make Animations whilst using GridBag Layout.
Are these possible and how? Any tutorials, help and suc
This is the program which i did long time back when i just started my Java
classes.I did simple animations on different tabs on JTabbedPane
(change the path of images/sound file as required),hope this helps:
UPDATE:
Sorry about not following concurrency in Swing.
Here is updated answer:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class ClassTestHello extends JApplet {
private static JPanel j1;
private JLabel jl;
private JPanel j2;
private Timer timer;
private int i = 0;
private int[] a = new int[10];
@Override
public void init() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
start();
paint();
}
});
}
public void paint() {
jl = new JLabel("hiii");
j1.add(jl);
a[0] = 1000;
a[1] = 800;
a[2] = 900;
a[3] = 2000;
a[4] = 500;
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
if(i % 2 == 0)
jl.setText("hiii");
else
jl.setText("byee");
i++;
if(i > 4)
i=0;
timer.setDelay(a[i]);
}
};
timer = new Timer(a[i], actionListener);
timer.setInitialDelay(0);
timer.start();
}
@Override
public void start() {
j1 = new JPanel();
j2 = new JPanel();
JTabbedPane jt1 = new JTabbedPane();
ImageIcon ic = new ImageIcon("e:/guitar.gif");
JLabel jLabel3 = new JLabel(ic);
j2.add(jLabel3);
jt1.add("one", j1);
jt1.addTab("hii", j2);
getContentPane().add(jt1);
}
}
In order to perform any kind of animation of this nature, you're going to need some kind of proxy layout manager.
It needs to determine the current position of all the components, the position that the layout manager would like them to have and then move them into position.
The following example demonstrates the basic idea. The animation engine use is VERY basic and does not include features like slow-in and slow-out fundamentals, but uses a linear approach.
public class TestAnimatedLayout {
public static void main(String[] args) {
new TestAnimatedLayout();
}
public TestAnimatedLayout() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestAnimatedLayoutPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestAnimatedLayoutPane extends JPanel {
public TestAnimatedLayoutPane() {
setLayout(new AnimatedLayout(new GridBagLayout()));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
add(new JLabel("Value:"), gbc);
gbc.gridx++;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
add(new JComboBox(), gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.gridwidth = 2;
add(new JScrollPane(new JTextArea()), gbc);
gbc.gridwidth = 0;
gbc.gridy++;
gbc.gridx++;
gbc.weightx = 0;
gbc.weighty = 0;
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.EAST;
add(new JButton("Click"), gbc);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class AnimatedLayout implements LayoutManager2 {
private LayoutManager2 proxy;
private Map<Component, Rectangle> mapStart;
private Map<Component, Rectangle> mapTarget;
private Map<Container, Timer> mapTrips;
private Map<Container, Animator> mapAnimators;
public AnimatedLayout(LayoutManager2 proxy) {
this.proxy = proxy;
mapTrips = new WeakHashMap<>(5);
mapAnimators = new WeakHashMap<>(5);
}
@Override
public void addLayoutComponent(String name, Component comp) {
proxy.addLayoutComponent(name, comp);
}
@Override
public void removeLayoutComponent(Component comp) {
proxy.removeLayoutComponent(comp);
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return proxy.preferredLayoutSize(parent);
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return proxy.minimumLayoutSize(parent);
}
@Override
public void layoutContainer(Container parent) {
Timer timer = mapTrips.get(parent);
if (timer == null) {
System.out.println("...create new trip");
timer = new Timer(125, new TripAction(parent));
timer.setRepeats(false);
timer.setCoalesce(false);
mapTrips.put(parent, timer);
}
System.out.println("trip...");
timer.restart();
}
protected void doLayout(Container parent) {
System.out.println("doLayout...");
mapStart = new HashMap<>(parent.getComponentCount());
for (Component comp : parent.getComponents()) {
mapStart.put(comp, (Rectangle) comp.getBounds().clone());
}
proxy.layoutContainer(parent);
LayoutConstraints constraints = new LayoutConstraints();
for (Component comp : parent.getComponents()) {
Rectangle bounds = comp.getBounds();
Rectangle startBounds = mapStart.get(comp);
if (!mapStart.get(comp).equals(bounds)) {
comp.setBounds(startBounds);
constraints.add(comp, startBounds, bounds);
}
}
System.out.println("Items to layout " + constraints.size());
if (constraints.size() > 0) {
Animator animator = mapAnimators.get(parent);
if (animator == null) {
animator = new Animator(parent, constraints);
mapAnimators.put(parent, animator);
} else {
animator.setConstraints(constraints);
}
animator.restart();
} else {
if (mapAnimators.containsKey(parent)) {
Animator animator = mapAnimators.get(parent);
animator.stop();
mapAnimators.remove(parent);
}
}
}
@Override
public void addLayoutComponent(Component comp, Object constraints) {
proxy.addLayoutComponent(comp, constraints);
}
@Override
public Dimension maximumLayoutSize(Container target) {
return proxy.maximumLayoutSize(target);
}
@Override
public float getLayoutAlignmentX(Container target) {
return proxy.getLayoutAlignmentX(target);
}
@Override
public float getLayoutAlignmentY(Container target) {
return proxy.getLayoutAlignmentY(target);
}
@Override
public void invalidateLayout(Container target) {
proxy.invalidateLayout(target);
}
protected class TripAction implements ActionListener {
private Container container;
public TripAction(Container container) {
this.container = container;
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("...trip");
mapTrips.remove(container);
doLayout(container);
}
}
}
public class LayoutConstraints {
private List<AnimationBounds> animationBounds;
public LayoutConstraints() {
animationBounds = new ArrayList<AnimationBounds>(25);
}
public void add(Component comp, Rectangle startBounds, Rectangle targetBounds) {
add(new AnimationBounds(comp, startBounds, targetBounds));
}
public void add(AnimationBounds bounds) {
animationBounds.add(bounds);
}
public int size() {
return animationBounds.size();
}
public AnimationBounds[] getAnimationBounds() {
return animationBounds.toArray(new AnimationBounds[animationBounds.size()]);
}
}
public class AnimationBounds {
private Component component;
private Rectangle startBounds;
private Rectangle targetBounds;
public AnimationBounds(Component component, Rectangle startBounds, Rectangle targetBounds) {
this.component = component;
this.startBounds = startBounds;
this.targetBounds = targetBounds;
}
public Rectangle getStartBounds() {
return startBounds;
}
public Rectangle getTargetBounds() {
return targetBounds;
}
public Component getComponent() {
return component;
}
public Rectangle getBounds(float progress) {
return calculateProgress(getStartBounds(), getTargetBounds(), progress);
}
}
public static Rectangle calculateProgress(Rectangle startBounds, Rectangle targetBounds, float 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, float 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 Dimension calculateProgress(Dimension startSize, Dimension targetSize, float 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;
}
public static int calculateProgress(int startValue, int endValue, float fraction) {
int value = 0;
int distance = endValue - startValue;
value = (int) ((float) distance * fraction);
value += startValue;
return value;
}
public class Animator implements ActionListener {
private Timer timer;
private LayoutConstraints constraints;
private int tick;
private Container parent;
public Animator(Container parent, LayoutConstraints constraints) {
setConstraints(constraints);
timer = new Timer(16, this);
timer.setRepeats(true);
timer.setCoalesce(true);
this.parent = parent;
}
private void setConstraints(LayoutConstraints constraints) {
this.constraints = constraints;
}
public void restart() {
tick = 0;
timer.restart();
}
protected void stop() {
timer.stop();
tick = 0;
}
@Override
public void actionPerformed(ActionEvent e) {
tick += 16;
float progress = (float)tick / (float)1000;
if (progress >= 1f) {
progress = 1f;
timer.stop();
}
for (AnimationBounds ab : constraints.getAnimationBounds()) {
Rectangle bounds = ab.getBounds(progress);
Component comp = ab.getComponent();
comp.setBounds(bounds);
comp.invalidate();
comp.repaint();
}
parent.repaint();
}
}
}
Update
You could also take a look at AurelianRibbon/Sliding-Layout