Win a copy of Java Concurrency Live Lessons this week in the Threads forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Updating UI  RSS feed

 
simon fletcher
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When instantiating a class that uses swing objects and methods, in order to run it all in the Event Dispatch Thread, one should use the swing.invokeLater() method. (That said, I have seen a lot of code examples on the internet that don't do this and am guessing they are just older pieces of code).

Anyway, my question is, if you have code doing things in threads other that EDT, what should be done when you want to pass variables from these other threads to the UI? Are there methods for this? A nudge in the right direction would be much appreciated. Thanks.

 
Piet Souris
Rancher
Posts: 1783
55
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi Simon,

well, indeed, starting your GUI by simply stating "new GUIClass()" from the main method does work.
My IDE usually inserts this invokeLater for me, and it also works. I'm not sure what exactly the problem is,
but no doubt one of our GUI-experts can answer that.

When using other threads than the EDT, you usually make use of some shared variables. You must be aware
of the dangers (especially thread interference and memory inconsistencies), but if you know what you are doing, it is not that complicated.

There is a nice class called SwingWorker that you could use as well.

As always, there is a lot to read on this subject. See the Oracle tutorials for concurrency and SwingWorker.

Greetz,
Piet
 
Campbell Ritchie
Sheriff
Posts: 53779
128
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Horstmann and Cornell, Core Java II 8/e vol I page 341 wrote:NOTE: You will see many Swing programs that do not initialize the user interface in the event dispatch thread. It used to be perfectly acceptable to carry out the initialization in the main thread. Sadly, as Swing components got more complex, the developers of the JDK were no longer able to guarantee the safety of that approach. The probability of an error is extremely low, but you would not want to one of the unlucky few who encounter an intermittent problem. It is better to do the right thing, even if the code looks rather mysterious.
Same page:
We discuss the details in Chapter 14
There is an example on page 909 (ch 14). They have a “bad” thread which is started like thisThe example they use that in eventually throws array index out of bounds exceptions.
Same book, page 911 wrote:Place the Swing code in the run method of a class that implements the Runnable interface. Then, create an object of that class and pass it to the static invokeLater or invokeAndWait method…
The first time you call invokeLater you start the EDT. If you call it again, you move your run method into the EDT (or something like that).
 
Piet Souris
Rancher
Posts: 1783
55
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Right, thanks.

So, I guess it is "Goodbye, new GUIClass()" and "Welcome, invokeLater()"!

Greetz,
Piet
 
Campbell Ritchie
Sheriff
Posts: 53779
128
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, it's only SeeYaLater
You usually create the new GUIClass() in the run method, so you will see it later. Usually only a few milliseconds later, so you would hardly notice any difference.
 
simon fletcher
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have read about SwingWorker. I understand it as being used when you want to do "longer" tasks that touch the GUI which would bog down the EDT. There's no description that I saw as to what would be considered tasks appropriate in length but that's a whole other topic.

Basically I can't seem to get my head around something like, say, you had a video game, for example, that might be crunching lots of data and updating the GUI all the time. If the body of data and the manipulation of it is small, it could happen in EDT, and if long, in a SwingWorker thread. If that's the case then any program using a GUI would be using the EDT and SwingWorker threads only, and never use any other types of threads except for code that never touches the GUI or an initial thread in which to "kick off" the EDT. Does this seem right? Most examples I've come across in books and on the web seem to mostly just contain code that appears to run in the main thread or other threads and touch the GUI all over the place without seeming to worry about the consequences.



 
Piet Souris
Rancher
Posts: 1783
55
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well first of all, JAVA is very fast and so you can do quite a lot of work on the EDT,
before you would notice any 'yerkiness' in your GUI.

But say you have a chess program that is thinking about its next move. It is probably
analysing millions of positions taking a couple of minutes. If you would do that on the
EDT, then your GUI is frozen for that time.

Indeed, I have myself asked why I read so little of SwingWorker, since its done()
method looks quite apropriate (it is invoked on the EDT). Maybe it has some drawbacks
that I am not aware of? Or maybe just unfamiliarity?

That said, I must say that the examples in the SwingWorker tutorial scare me off
a little bit. If you look at their 'Flipper' example, well, they are creating millions of Flipper
objects...
But I see no reason why a SwingWorker couldn't be used just like any other Thread.

And yes, letting Threads change variables all over, well, it usually works fine, but be aware
of the risks.
As a minimum: you must know about synchronization.
 
Campbell Ritchie
Sheriff
Posts: 53779
128
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Downloading files from the net? Even if you have several megabytes/second broadband, a large file can take several seconds or minutes to download. If you download it on the EDT, your GUI will not respond until it is finished.
 
simon fletcher
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In response to C. Ritchie, it looks like the info used in your response is suggesting that, once the EDT is started, a method belonging to objects instantiated in the main thread, or some other non-EDT, could be called within a run() method within an anonymous Runnable within SwingUtilities.invokeLater() method and that would be the link from a non-EDT to the EDT. Obviously there will only be the one EDT and any calls to any run() methods - defined within invokeLater() methods- after the one that starts the EDT will simply run code within the EDT. Does that sound right?

I guess the obvious response to this is to see what happens if I try it.
 
Campbell Ritchie
Sheriff
Posts: 53779
128
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
simon fletcher wrote: . . . Does that sound right?
Yes, it does.

I guess the obvious response to this is to see what happens if I try it.
This is an instance where the obvious can be incorrect; you may have infrequent and intermittent problems and not notice them when you try it out.

Find the example in Horstmann a few pages after page 911 and try it. That is specially designed to go wrong if you go outside the EDT.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!