How could I add a simple delay in a Java Swing application?

Solution 1:

Here's an example using a javax.swing.Timer

public class TestBlinkingText {

    public static void main(String[] args) {
        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();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new BlinkPane());
                frame.setSize(200, 200);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }            
        });
    }

    protected static class BlinkPane extends JLabel {

        private JLabel label;
        private boolean state;

        public BlinkPane() {

            label = new JLabel("Look at me!");
            setLayout(new GridBagLayout());

            add(label);

            Timer timer = new Timer(500, new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent ae) {                    
                    state = !state;
                    if (state) {
                        label.setForeground(Color.RED);
                    } else {
                        label.setForeground(Color.BLACK);
                    }                    
                    repaint();                    
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.setInitialDelay(0);
            timer.start();            
        }        
    }    
}

Solution 2:

Good thing you removed the Thread.sleep as that would make your UI unresponsive for those 2 seconds.

What you can do is start a Timer which only runs once:

int delay = 2000;
Timer timer = new Timer( delay, new ActionListener(){
  @Override
  public void actionPerformed( ActionEvent e ){
    jLabel12.setForeground( Color.red );
  }
} );
timer.setRepeats( false );
timer.start();

Note that the Timer is a javax.swing.Timer, which assures that the actionPerformed method of the ActionListener is called on the Event Dispatch Thread, respecting the Swing threading rules.

This is also possible with a SwingWorker, but I would stick to the Timer for this. In case you want to use the SwingWorker, you can simply use Thread.sleep in the doInBackground() method, and update the JLabel in the done() method.

Something along the lines of

class Delay extends SwingWorker<Void, Object> {
 @Override
 public void doInBackground() {
  Thread.sleep( 2000 );
 }

 @Override
 protected void done() {
   jLabel12.setForeground( Color.red );
 }
}