Search code examples
javaswingtimerthread-sleep

Update label twice in one timer operation


I have a class Dmi,Swing components frame and a label.

I have Swing timer. In timer implementation I have two statements for setting text in the label, with a time interval, but I can only see the last setText operation.

import javax.swing.*;
import java.util.Timer.*;
import java.awt.event.*;
class Dmi implements ActionListener
{

Timer tim;
JFrame frame;
JLabel lbl;
Dmi()
{
    frame=new JFrame("abc");
    lbl=new JLabel("count");
    frame.add(lbl);
    frame.setVisible(true);
    frame.pack();
    tim=new Timer(1000,this);
    tim.start();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent ae) 
{
    Thread th1=new Thread();
    lbl.setText("abc");
    try
    {
        th1.sleep(300); 
    }
    catch (Exception e)
    {
        System.out.println(e);
    }
    lbl.setText("ddd:");

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

Solution

  • Start by taking a closer look at Concurrency in Swing and How to use Swing Timers

    A Swing Timer will generate ActionEvents WITHIN the Event Dispatching Thread, which makes them really good for updating the UI from within.

    However, your code...

    public void actionPerformed(ActionEvent ae) 
    {
        Thread th1=new Thread();
        lbl.setText("abc");
        try
        {
            th1.sleep(300); 
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
        lbl.setText("ddd:");
    
    }
    

    is blocking the Event Dispatching Thread (through the use of Thread#sleep), which will prevent the EDT from process new repaint events or any other user based events, making your program look as if it's hung.

    You're either going to have to devise a solution which allows you to determine the amount of time the timer has been running and change the state based on that or possibly use a SwingWorker instead

    For example...

    import java.awt.EventQueue;
    import java.util.List;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.SwingWorker;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Dmi {
    
        JFrame frame;
        JLabel lbl;
    
        Dmi() {
            frame = new JFrame("abc");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            lbl = new JLabel("count");
            frame.add(lbl);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
    
            Worker worker = new Worker();
            worker.execute();
        }
    
        public class Worker extends SwingWorker<String, String> {
    
            @Override
            protected String doInBackground() throws Exception {
                while (!isCancelled()) {
                    Thread.sleep(1000);
                    publish("abc");
                    Thread.sleep(300);
                    publish("def");
                }
                return null;
            }
    
            @Override
            protected void process(List<String> chunks) {
                lbl.setText(chunks.get(chunks.size() - 1));
            }
    
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
                    Dmi dmi = new Dmi();
                }
            });
        }
    }