Ava
Ava

Reputation: 51

(multiple image ) animation Java

I have got a set of nodes in my program, each have a specific x,y location. and each have a set of image icons.

I want to draw image animation for each nodes at its specific location.

Here is my code: (this only shows the last image which i know why!.)

public void showPicture()  {
        //nodes : 
        for(int i=0;i<thisGraph.getNode().size();i++){
            if(thisGraph.getNode().get(i).getImageIcon()!=(null)){
                for(int j=0;j<thisGraph.getNode().get(i).getImageIcon().size();j++){
                    if(j>0)
                       lables.get(lables.size()-1).setVisible(false);
                    JLabel jLabel1 = new JLabel();
                    lables.add(jLabel1);
                    jLabel1.setLayout(new GridBagLayout());
                    jLabel1.setIcon(thisGraph.getNode().get(i).getImageIcon().get(j));
                    jLabel1.setVisible(true);
                    jLabel1.setBounds((int)thisGraph.getNode().get(i).getX(),(int)thisGraph.getNode().get(i).getY(),195,163);           
                    jPanel1.add(jLabel1);

                }
            }
        }
    }

This method showPicture() is called in a buttonActionListener. And I also have another button which I want it to stop the image animations for all labels.

What I have tried: Thread.sleep() -> it freezes the button and it only shows the last image

I figured I had to use timer, but through all the topics I went they only used it on one label, not multiple labels.

Edit -> i read those examples given in the comments . and here is what i have resolved but it still is freezes the button and doesn't works :

int j = 0;
    public void showPicture(){
        //nodes : 
        for(int i=0;i<thisGraph.getNode().size();i++){
            if(thisGraph.getNode().get(i).getImageIcon()!=(null)){
              j=0;
                while( j<thisGraph.getNode().get(i).getImageIcon().size()){

                    if(j>0)
                        lables.get(lables.size()-1).setVisible(false);
                    JLabel jLabel1 = new JLabel();
                    lables.add(jLabel1);
                    jLabel1.setLayout(new GridBagLayout());
                    jLabel1.setIcon(thisGraph.getNode().get(i).getImageIcon().get(j));
                    jLabel1.setVisible(true);
                    jLabel1.setBounds((int)thisGraph.getNode().get(i).getX(),(int)thisGraph.getNode().get(i).getY(),195,163);

                    jPanel1.add(jLabel1);

                    //

                    ActionListener act;
                    act = new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            jLabel1.setVisible(true);        
                            j++;
                        }
                    };
                    Timer timer = new Timer(1000, act );
                    timer.start();

                    timer.stop();
                    //

                }
            }
        }}

Upvotes: 0

Views: 225

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347332

Swing is single threaded and not thread safe. This means that you shouldn't block the Event Dispatching Thread with long running or blocking operations, like Thread.sleep. You should also, only ever update the UI (or anything it relies on) from within the context of the Event Dispatching Thread.

See Concurrency in Swing for more details.

Probably the simplest solution to your problem is to use a Swing Timer.

The idea is a you use a single Timer to act as the "main animation loop", changing the properties of ALL the objects you need updated within it.

The following is pretty basic example, it animates 100 JLabels, simply changing their background color with a randomly picked color

Sparkle

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class Test {

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

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

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

    public class TestPane extends JPanel {

        private List<JLabel> nodes = new ArrayList<>(100);

        private Random random = new Random();
        private Color[] colors = new Color[] { Color.RED, Color.GREEN, Color.BLUE, Color.BLACK, Color.MAGENTA};

        public TestPane() {
            setLayout(new GridLayout(0, 10));
            for (int index = 0; index < 100; index++) {
                JLabel label = new JLabel();
                label.setBorder(new EmptyBorder(5, 5, 5, 5));
                label.setOpaque(true);
                label.setBackground(pickColor());
                nodes.add(label);
                add(label);
            }
            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    for (JLabel label : nodes) {
                        label.setBackground(pickColor());
                    }
                }
            });
            timer.start();
        }

        protected Color pickColor() {
            return colors[random.nextInt(colors.length)];
        }

    }

}

See How to Use Swing Timers for more details

Upvotes: 1

Related Questions