Re: How to change JPanels?
On 16/02/11 13:37, Eric wrote:
On Feb 15, 6:21 pm, Lew <no...@lewscanon.com> wrote:
Tell us what part ofhttp://download.oracle.com/javase/tutorial/uiswing/concurrency/dispat...
is not clear and we'll help.
What's not clear is how there can be only one EDT.
Have you really read that article? It's vital you understand what it
says, and it's apparent that you do not.
There is only one EDT. It is created by Swing, you have no control over
it. You can request that some of your code be run on that thread, but
you can not magically create another thread which does what the EDT
does, nor should you run any code which modifies or accesses GUI
components on any other thread (barring some exceptions which are
specified in their API docs).
EDT means event
dispatching thread. If there's only one thread, how can it be 2
threads?
What?
I call a SwingWorker's execute method. This starts a new thread, no?
Yes.
After that method call I can call another method which updates a gui
object. This must be on *the* EDT, no?
It is most likely so, yes. If you invoked the SwingWorker.execute()
method on the EDT then when it returns your code is still running in the
EDT. There really isn't much point using SwingWorker in any thread other
than the EDT.
In that SwingWorker object
I'm supposed to be able to execute gui commands in the done method,
no? Didn't I have 2 threads? How do I now have only one?
You do not appear to properly understand threads. You really need to
understand threads to make this work.
It's not actually that complicated.
At some unspecified time Swing will create the EDT. It does so when it
needs to, and you should not concern yourself with when it does so.
Swing runs on the EDT, and the EDT processes all events from the GUI.
When you initially create your GUI you must follow the coding guidelines
set out in the tutorial above. The GUI creation code must be run on the
EDT, and you do that using SwingUtilites. This requests that Swing run a
certain piece of your code on the EDT. This is essential for thread
safety, so that while your code is creating the GUI Swing isn't doing
anything else.
After you've done that there will be 2 threads running, your main thread
and the EDT. Your main thread is likely to be doing nothing at this
point, the EDT is waiting to act on events from the GUI.
When an action occurs on the GUI the Swing processes that event (on the
EDT) and invokes any event handlers which are registered for that event.
This most likely means code that you wrote, but it is run by Swing on
the EDT. Swing determines the appropriate time to invoke your code.
Until your code returns control of the EDT back to Swing no further
events, or screen updates, will occur. The GUI is entirely blocked.
If you need to perform some long running task in your event handler code
then you should offload this task to a SwingWorker so that the EDT can
get back to handling events. If you don't do this the GUI will become
unresponsive. If you do start a SwingWorker thread you now have 3
threads running. Your event handler code will continue execution on the
EDT. At this point your event handler code can update GUI components
quite safely, but no effect will be seen until your code returns.
allowing Swing to process those updates.
When the SwingWorker thread completes, the SwingWorker object will
invoke its done() method. This it will do on the EDT, it is taken care
of for you by SwingWorker. Because it is run on the EDT the done()
method can also update GUI components quite safely, but as with your
event handler code, no effect will be seen on the GUI until your code
returns, handing control of the EDT back to Swing.
must be running on an EDT. If it's [sic] menu action listener needs to run
Only if you take care to be sure that it does, unlike what you did in your code.
This doesn't make sense. You can have a menu action listener method
which isn't running on the EDT?
You didn't create the GUI on the EDT. Once you have broken that cardinal
rule, all bets are off. You have a potential race condition in the
creation of the GUI objects, and they are in an indeterminate state.
This may result in all kinds of unpredictable behaviour.
some time consuming code it creates a SwingWorker, so that would start
No, *you* create the SwingWorker. You're the programmer.
Semantics. The java interpreter creates a SwingWorker. I write the
code that tells it to do so.
a new thread which would presumably not be an EDT, but it has a done
Not "presumably", actually and by documented design and purpose, as you would
know had you read the docs.
I did read the docs. Maybe it's just me but they're not entirely
clear. Is doInBackground not able to execute any gui commands, or is
it just not supposed to (bad form)?
It's not illegal for it modify GUI components, it won't fail to compile
or throw Exceptions (actually it may throw Exceptions). However, it's
not just bad form, it's forbidden by the rules of thread safety. It
breaks the contract between you and Swing that you won't modify the GUI
in any way on any thread other than the EDT. If you do you potentially
have two threads modifying the same object at the same time, furthermore
Swing doesn't know you've changed anything so won't update the GUI.
Swing will laugh at you and make your life a misery.
I see in the docs how to start
new threads and how to use the EDT but aside from executing the
javax.swing.SwingUtilities.isEventDispatchThread method, I didn't see
a clear explanation in the docs of how to know if a new thread was
started as an EDT.
No other thread can ever be started as the EDT. There is only ever one
EDT, and it's started by Swing. No thread you create can ever take over
that task.
method to update the gui [sic] which is either creating another new thread
which is an EDT or is somehow linked to the thread which created the
You really have not read the material. There is only *one* EDT!
Are you familiar with a little web site called "Google"?
I'm here to learn. If you're only here to insult don't respond. I've
been writing Java for years but I'm new to the gui. I've been writing
gui for years through another language which handles the threading
automatically.
For the time being follow this simple rule. Never create or modify any
GUI component on any thread other than the EDT unless the API docs for
that component state explicitly that you can. There are potential race
conditions which may manifest themselves in totally unpredictable and
unrepeatable ways if you violate this rule. Swing objects are NOT thread
safe. Access to them, including their constructors, is not synchronized
in any way. Break this rule at your peril.
First fix this problem in your code. We can't help you until you do,
because we cannot fix what Swing does when you create components off the
EDT. If you still have problems when you've done this, come back and let
us know.
--
Nigel Wade