Search code examples
javaswingwhile-loopactionlistenerjlabel

How to edit Jlabel every seconds?


How to edit the JLabel every seconds like (time left or score) in some games. this is my code

static int l = 1;
static int s = 5000;
static int t = 90;
public static void main(String[] args) {

    //Frame
    final JFrame f = new JFrame();
    f.setTitle("Picture Puzzle");
    f.setSize(500,500);
    f.setLocationRelativeTo(null);
    f.setResizable(false);
    f.setDefaultCloseOperation(EXIT_ON_CLOSE);
    f.setVisible(true);

//some extra stuffs here

    JLabel blevel00 = new JLabel("Level:" + l);
    JLabel bscore00 = new JLabel("Score:" + s);
    JLabel btime00 = new JLabel("Time:" + t);

    p2.add(blevel00);
    p2.add(bscore00);
    p2.add(btime00);

//some extra stuffs here

    start.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            while(t != 0 ) {   //the t is the static int t = 90;
            f.add(p2);
            f.remove(p1);
            f.setVisible(true);
            f.revalidate();
            f.repaint();
            }
            t--;
        }
    });

} }

I tried this and nothing happens. any help will be appreciated.


Solution

  • Swing is a single threaded environment, that is, all alterations and modifications to the UI are expected to occur within the context of the Event Dispatching Thread.

    Anything that blocks this thread, like a never ending loop or blocking I/O will prevent this thread from processing new events, including paint events.

    Swing provides a number of solutions to this problem, in your case the best solution is probably to use a javax.swing.Timer. This will allow you to schedule a regular callback that is called within the context of the EDT, allowing you to make modifications to the UI on a regular bases.

    Take a look at Concurrency in Swing and How to use Swing Timers for more details

    Update with simple example

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.EventQueue;
    import java.awt.Font;
    import java.awt.GridBagLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.text.DateFormat;
    import java.util.Date;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class SimpleClock {
    
        public static void main(String[] args) {
            new SimpleClock();
        }
    
        public SimpleClock() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
            private JLabel time;
            public TestPane() {
                setLayout(new GridBagLayout());
                time = new JLabel();
                time.setFont(time.getFont().deriveFont(Font.BOLD, 48));
                add(time);
                updateTime();
                Timer timer = new Timer(500, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        updateTime();
                    }
                });
                timer.start();
            }
    
            protected void updateTime() {
                time.setText(DateFormat.getTimeInstance().format(new Date()));
            }
        }
    
    }