0

I'm creating an animation using JLabel,

public void updateLabels() {
      label.setIcon(new ImageIcon(new Paint().getScaledImage(paint[currentIndexLabel].imageCALA,300,300)));
      label_1.setIcon(new ImageIcon(new Paint().getScaledImage(paint[currentIndexLabel].imageStates,300,300)));
      label_2.setIcon(new ImageIcon(new Paint().getScaledImage(paint[currentIndexLabel].imageStrategies,300,300)));
      label_3.setIcon(new ImageIcon(new Paint().getScaledImage(paint[currentIndexLabel].imagekD,300,300)));

      currentIndexLabel++;
}

and I have a button that updates the labels

btn.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent arg0) {
        while (currentIndexLabel != paint.length-1) {
            updateLabels();
        }
    }
});

But, I don't know how to wait, say for example 1000ms, until next change. When I add this:

try { Thread.sleep(1000); } catch (Exception e){}

into my ActionListener:

btn.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent arg0) {
           while (currentIndexLabel!=paint.length-1) {
             updateLabels();
             try { Thread.sleep(1000); } catch (Exception e){}
       }
    }
 });

its not working. It just stopping for a while and I don't see changes between the first and last frames. Is it possibile to Wait 1000ms without stopping the program? When I delete the while loop and try section, and click my button it is changing pretty well...

How can I do this?

Software Engineer
  • 15,457
  • 7
  • 74
  • 102
Potato
  • 172
  • 1
  • 12
  • try looking into this - https://stackoverflow.com/questions/149153/loading-animated-gif-from-jar-file-into-imageicon. Seems like much more reasonable approach to load directly animated gif than using four labels – Jan Hruby Feb 25 '19 at 11:58

1 Answers1

10

Using Thread#sleep method in swing applications in main thread will cause the GUI to freeze (since the thread sleeps, events cannot take place). Thread#sleep method in swing applications is only allowed to be used only by SwingWorkers, and this in their #doInBackround method.

In order to wait in a swing application (or do something periodically), you will have to use a Swing Timer. Take a look at an example i have made:

import java.awt.FlowLayout;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer; //Note the import

public class TimerExample extends JFrame {
    private static final int TIMER_DELAY = 1000;
    private Timer timer;

    public TimerExample () {
        super();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(200, 200);
        setLocationRelativeTo(null);
        getContentPane().setLayout(new FlowLayout());

        timer = new Timer(TIMER_DELAY, e -> {
            System.out.println("Current Time is: " + new Date(System.currentTimeMillis()));
        });
        //timer.setRepeats(false); //Do it once, or repeat it?
        JButton button = new JButton("Start");
        button.addActionListener(e -> timer.start());
        getContentPane().add(button);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new TimerExample().setVisible(true));
    }
}

Output after "Start" button is pressed:

Current Time is: Mon Feb 25 13:30:44 EET 2019

Current Time is: Mon Feb 25 13:30:45 EET 2019

Current Time is: Mon Feb 25 13:30:46 EET 2019

As you can see, Timer's action listener fires every second.

So in your case:

timer = new Timer(TIMER_DELAY, e -> {
    if (currentIndexLabel != paint.length-1) {
        upateLabels();
        timer.restart(); //Do this check again after 1000ms
    }
});
button.addActionListener(e -> timer.start());
Community
  • 1
  • 1
George Z.
  • 6,643
  • 4
  • 27
  • 47
  • But how to use it in my code, i see that you replace event of ActionListener, when i trying to make similar thing it doesn't working :D – Potato Feb 25 '19 at 12:29
  • hmm i have error in this place, my compliator underline whole text which is comming from you. `Multiple markers at this line - Line breakpoint:MyCanvasInWindow [line: 95] - MyCanvasInWindow(Paint[]) - The constructor Timer(int, ( e) -> {}) is undefined` – Potato Feb 25 '19 at 14:43
  • 1
    @Potato Hmmm...What java version do you use? – George Z. Feb 25 '19 at 14:44
  • 1
    @Potato Also did you notice Timer's package? `import javax.swing.Timer;` – George Z. Feb 25 '19 at 14:44
  • haha i noticed that i have different Timer in my imports, but stil i have error with that arrow `Multiple markers at this line - Syntax error, insert "... VariableDeclaratorId" to complete FormalParameterList - Syntax error on token "->", @ expected - Syntax error, insert "[ ]" to complete Dimension` – Potato Feb 25 '19 at 14:46