call SwingUtilities.invokeLater(Runnable) in constructor

M

Martijn Mulder

I understand the need to create Swing components in the EDT (I don't like it
but that's another story). Is it OK to create the necessary Runnable object
and make the call to SwingUtilities.invokeLater() method from within the
constructor of the descendent of the javax.swing.JFrame that I wish to
create at runtime?
 
O

opalpa

Hmm. I do not think it is OK because of the constructor being a JFrame
constructor. The first thing a constructor does is call super, if I
remember right, so you will be executing the super class's (that is
JFrame's ) constructor out of Swing thread.

Perhaps what you could do is provide a factory method that will enclose
your constructor in Swing thread and make constructor private.

Opalinski
(e-mail address removed)
http://www.geocities.com/opalpaweb/
 
K

Knute Johnson

Martijn said:
I understand the need to create Swing components in the EDT (I don't like it
but that's another story). Is it OK to create the necessary Runnable object
and make the call to SwingUtilities.invokeLater() method from within the
constructor of the descendent of the javax.swing.JFrame that I wish to
create at runtime?

Martijn:

I'm not sure why you want to do that but if you are in the constructor
of a Swing component you should already be in the EDT. So if you are
following the rule that Swing GUIs are created in the EDT you can't get
into the position you want to be in. All that aside, just ignore the
rule. It will most likely work anyway. I had difficulty figuring out
how to make this happen when I first started following the rule but now
it is no big deal.

What is the reason the you don't want to create your GUI components on
the EDT?
 
A

Alex Hunsley

Martijn said:
I understand the need to create Swing components in the EDT (I don't like it
but that's another story).

AFAICR you must *realise* or *affect realised* Swing components in the
EDT. You can create them where you like.
In other words, creating a JFrame like so can be done anywhere:

JFrame frame = new JFrame("I was framed!!");

but when you realise it:

frame.show();

or affect it when already showing:

// frame is already showing
frame.setLayout( ... );

this must be done in the event dispatch thread.

Is it OK to create the necessary Runnable object
and make the call to SwingUtilities.invokeLater() method from within the
constructor of the descendent of the javax.swing.JFrame that I wish to
create at runtime?

I seriously recommend not realising Swing objects (i.e. calling show()
or calling a method which calls show() or similar) from constructors.
Sadly I have no examples to hand, but it's not a great idea and you can
run into problems with it - I've seen several such problems.
Also, purely in terms of style, you'd be confusing the creation of a GUI
object with the showing of same, which are two different concepts (and
for good reasons).
The basic rule is: if you do something which realises a component, or
affects a realised component, you should be doing it from the event
dispatch thread. Normally people transparently do this anyway: for
example, event handling code (e.g. handling a mouse click) gets called
on the EDT, so their subsequent call from that method to affect a
showing GUI item isn't naughty.
If you don't follow this rule, you may not immediately notice anything
going wrong: but you may notice problems later, with your program
suffering unpredictable GUI behaviour, which can be annoying. I've often
found myself wishing that Java was more aware of the breaking of the
basic rule (that I mentioned above) and warned you when you were doing it...

A common pattern where people often trip up: they make their program do
some processing in a seperate thread, which then updates the GUI at the
end of processing without being aware of the fact that it's not on the EDT!

Btw, consider following the normal design of having a normal class
method which causes the item to be realised (and don't just call this
method at the end of the constructor, or you're just ending up in the
same place.)
The constructor should just construct, not show.

In terms of a coding solution to these issues, I have a fairly simple
utility method I wrote a while back, which makes it easier execute a
Runnable under different circumstances. The method signature is
something like this:

void launchRunnable(Runnable runnable,
boolean blocking,
boolean onEventDispatchThread)

If 'blocking' is true, the method won't return till the runnable has
finished (otherwise the runnable has started in a new thread, then the
method returns immediately). And the 'onEventDispatchThread' parameter
does what it says: it will launch the Runnable on the EDT if you like.
(So you'd set this to true if you were showing or affecting a showing
Swing component.)

I'll find the code perhaps and post it, it's pretty short.
 
N

Nigel Wade

Knute said:
Martijn:

I'm not sure why you want to do that but if you are in the constructor
of a Swing component you should already be in the EDT. So if you are
following the rule that Swing GUIs are created in the EDT you can't get
into the position you want to be in. All that aside, just ignore the
rule. It will most likely work anyway. I had difficulty figuring out
how to make this happen when I first started following the rule but now
it is no big deal.

I would not follow this advice. It might work now, it might work tomorrow, but
one day it will surely fail. I've been in the position of tracking down one of
these intermittent bugs, and I wouldn't recommend anyone else try to locate
one. If you create components on a non-EDT thread, and during the creation the
EDT has to perform a repaint the partially constructed component may access
references which are null, and other values which are invalid. The results are
undefined.
What is the reason the you don't want to create your GUI components on
the EDT?

That is a very pertinent question. Normally you create GUI components on the fly
in response to some GUI interaction, and are therefore executing a callback
which is running in the EDT anyway.
 
T

Thomas Weidenfeller

Alex said:
AFAICR you must *realise* or *affect realised* Swing components in the
EDT. You can create them where you like.

No, Sun changed the rule. Details are in the FAQ.

/Thomas
 
T

Thomas Hawtin

Nigel said:
one. If you create components on a non-EDT thread, and during the creation the
EDT has to perform a repaint the partially constructed component may access
references which are null, and other values which are invalid. The results are
undefined.

Repaints (and revalidates) aren't a problem. The component wont be
"realised", and therefore the call to repaint will not do anything.

Most of the problems are to do with Swing text attempting thread-safety.
The bulk of Swing is thread-agnostic. In order to notify the
thread-agnostic code of changes made from thread-safe code, control is
handed back over to one particular thread (the EDT). So, the
thread-agnostic code is accessed by a particular thread, and so actually
becomes thread-hostile.

Tom Hawtin
 
T

Thomas Hawtin

Alex said:
AFAICR you must *realise* or *affect realised* Swing components in the
EDT. You can create them where you like.

It turns out you need to create some of them on the EDT too. So the rule
is, create them all on the EDT.
In terms of a coding solution to these issues, I have a fairly simple
utility method I wrote a while back, which makes it easier execute a
Runnable under different circumstances. The method signature is
something like this:

void launchRunnable(Runnable runnable,
boolean blocking,
boolean onEventDispatchThread)

Where that method is used, aren't those flags almost always going to be
constants? In that case it will be very much clearer to have separate
methods.

Tom Hawtin
 
O

opalpa

That is a very pertinent question. Normally you create GUI components on the fly
in response to some GUI interaction, and are therefore executing a callback
which is running in the EDT anyway.

Two places where GUI components frequently get created and are not in
response to GUI interaction are:
A) the first GUI thing that makes it possible to have GUI
interactions
B) data driven displays where data properties result in
number&arrangment&type

I understand, however, that when making applications with
"File,Edit,View,...,HELP" menu then GUI components are made in response
to GUI interactions.

Opalinski
(e-mail address removed)
http://www.geocities.com/opalpaweb/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top