1

I am trying to do the following: click a button, button disappears for 2 seconds, text appears for 2 seconds and after those 2 seconds the visibility is reversed. So far I have done this:

btnScan.addActionListener(new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            txtScanning.setVisible(true);
            btnScan.setVisible(false);
               try {
                Thread.sleep(2000);                 //1000 milliseconds is one second.
                } catch(InterruptedException ex) {
                Thread.currentThread().interrupt();
                }
               }
            btnScan.setVisible(true);
        }

    });

and the result is that as soon as I click the btnScan, the whole program freezes for 2 seconds before doing anything. How do I add the delay at the correct order?

ZakiMak
  • 2,072
  • 2
  • 17
  • 26
deadpixels
  • 769
  • 1
  • 12
  • 21

4 Answers4

2

You should not call sleep method in your code that dispatches the event. All the work related UI is handled by EDT(Event Dispatch Thread) and a sleep method will cause it to freeze and hence your Swing application will freeze.

To overcome it you should use a Timer. Run the timer and execute the UI manipulation using SwingUtilities.invokeLater so that it is handled by EDT.

import java.util.Timer;

// make it a member variable
Timer timer = new Timer();
........
    public void actionPerformed(java.awt.event.ActionEvent evt) {                                       

        button.setVisible(false);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                SwingUtilities.invokeLater(new Runnable() {

                    public void run() {
                        button.setVisible(true);
                    }
                });

            }
        }, 2000);

    }
ZakiMak
  • 2,072
  • 2
  • 17
  • 26
0

Currently in your code, you are causing the EDT (event dispatcher thread) to pause with the invocation of Thread.sleep
Performing any long running tasks in the EDT will cause your UI to freeze.

To achieve what you desire, use a SwingWorker thread to perform your actions
This might help: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

MJSG
  • 1,035
  • 8
  • 12
0

Swing is a single threaded environment, anything that blocks this thread will prevent it from processing new events, including repaint requests.

Swing is also not thread safe, meaning img you should never create or update the UI from outside the context of the EDT.

In this case you can use a Swing Timer to trigger a callback to occur at some time in the future which (the notification) will be executed within the context of the EDT, making it safe to update the UI with

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

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

Making use of Swing timer, you can do something like this:

btnScan.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        txtScanning.setVisible(true);
        btnScan.setVisible(false);
        Timer timer = new Timer(2000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent acv) {
                btnScan.setVisible(true);
                txtScanning.setVisible(false);
            }
        });

        // setRepeats(false) to make the timer stop after sending the first event
        timer.setRepeats(false);
        timer.start();
    }
});
smac89
  • 39,374
  • 15
  • 132
  • 179