Bookmark Topic Watch Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Jeanne Boyarsky
  • Tim Cooke
Sheriffs:
  • Liutauras Vilda
  • paul wheaton
  • Henry Wong
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Frits Walraven
Bartenders:
  • Piet Souris
  • Himai Minh
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Report post to moderator
A common problem posted in the Swing forum is something like "I created a JButton, JTextComponent, etc. and update its value (text, color, etc.), but the display doesn't change immediately".

Generally the code leading to that kind of misbehaviour isn't following the rules of concurrency in Swing. An example of some code exhibiting this behavior is as follows:



I suggest that you copy the above code, compile and run it so you can get a sense of the problem.

If you have run the code, you will witness that the button freezes when you click on it and displays only the 'OK' text, never the 'Performing' text. And it never get's disabled at all. This is broken, for sure, but what is the problem?

The code that paints the GUI and events generated by the GUI are executed on a single thread, called the "event-dispatching thread" (EDT). (If you've never heard of "threads", consult the Java Tutorial on Threads here: http://java.sun.com/docs/books/tutorial/essential/threads/index.html. Threads make it possible to do several things at the same time in a single program.)

In the program above, we are using the EDT set a new text for our button, do some long running task and then set yet another text for the button. When calling methods like 'setText' or 'setEnabled' on a method new events for the EDT are internally generated (e.g. to repaint the component). Because we never leave the EDT and do our work (method 'doSomeWork') there, all subsequent generated events cannot be processed by the EDT until we leave the 'actionPerformed' method.

Now that we've identified the problem, how do we fix it? The answer in your case will depend on your program requirements and your comfort level with threads. The Java Swing Tutorial has a page on Concurrency and Swing (http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html) which is a good starting point for fixing this problem.

The simplest solution would be to use a SwingWorker thread that processes the long-running task(s) while the EDT is free to continue serving GUI events. So we modify our example from above to make use of a SwingWorker:



Now we start a separate thread (SwingWorker) that processes our long-running task (in background) while the GUI is still responsible. Therefore the text is updated and the button becomes disabled while the task is running. In the 'done' method of SwingWorker we reset the text and enable the button again. The differences in code aren't the big, are they?


CategoryCodeSamples
 
What do you have to say for yourself? Hmmm? Anything? And you call yourself a tiny ad.
Free, earth friendly heat - from the CodeRanch trailboss
https://www.kickstarter.com/projects/paulwheaton/free-heat
    Bookmark Topic Watch Topic
  • New Topic