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.