0

I want to paint a panel blue, then wait five seconds, then do other stuff.
Now I have the following piece of code, which I expect to do what I want. Here it is:

JPanel somePanel = getSomePanel();
somePanel.setBackground(Color.BLUE);
Object lock = new Object();
synchronized (lock) {
    try {
        lock.wait(5000);
    }
    catch (InterruptedException exc) { }
}
// Do other stuff

But instead, it waits five seconds and then paints the component blue.

  • Why first waiting, then painting blue, instead of vice versa? (I guess it has something to do with the Swing mechanism...?)
  • How to 'change that order'?
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
MC Emperor
  • 22,334
  • 15
  • 80
  • 130
  • 6
    Don't block the EDT (Event Dispatch Thread) - the GUI will 'freeze' when that happens. Instead of calling `Thread.sleep(n)` implement a Swing `Timer` for repeating tasks or a `SwingWorker` for long running tasks. See [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) for more details. – Andrew Thompson Jan 30 '13 at 12:30
  • @AndrewThompson but this works fine for me, Without using `invokeLater()` or `invokeAndWait()` this behaviour also depends upon different platforms? – joey rohan Jan 30 '13 at 12:33
  • 2
    *"depends upon different platforms?"* Platforms, JREs, moments in time, the humidity.. Not doing GUI edits on the EDT can cause 'unpredictable' behavior. Of course, the result of *blocking* the EDT **is** very predictable. – Andrew Thompson Jan 30 '13 at 12:39
  • `// Do other stuff` For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Jan 30 '13 at 12:40
  • 1
    Also see [this](http://stackoverflow.com/questions/14074329/using-sleep-for-a-single-thread/14074427#14074427) similar answer and [variation](http://stackoverflow.com/questions/14072940/threading-a-paint-method/14072987#14072987) – David Kroukamp Jan 30 '13 at 12:43
  • 1
    @AndrewThompson: and don't forget Look & Feel. I remember this one because I've been burned by it before! – Hovercraft Full Of Eels Jan 30 '13 at 14:26
  • @joeyrohan Sorry, forgot to add a notification to that last comment re 'platform'. :P – Andrew Thompson Jan 31 '13 at 03:44

3 Answers3

4

Do not wait in a GUI event handler - it prevents the processing of messages, eg. repaint requests.

Nothing GUI gets done while you are waiting on the lock.

Martin James
  • 24,453
  • 3
  • 36
  • 60
4

Don't do the synchronized code with locking on the Swing event thread as all you're doing is locking Swing itself and freezing the GUI. Google "Concurrency in Swing" for the details. Myself I'd use a Swing Timer for this. Note that your post uses the tag, but you don't actually do multithreading anywhere.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
3

The others are right, if you are waiting on the event dispatch thread, then this thread will not do any painting in the meantime.

There is a trick however, that should help you without starting a new thread: call paintImmediately after setting the background color.

somePanel.paintImmediately(0, 0, somePanel.getWidth(), somePanel.getHeight());
lbalazscs
  • 17,474
  • 7
  • 42
  • 50