views:

227

answers:

3

I'm working on Java Swing application with Google Guice as an IOC container. Things are working pretty well. There are some UI problems. When a standard L&F is replaced with Pushing pixels Substance L&F application is not running due to Guice's Swing components creation outside of UI thread.

Is there a way to tell Guice to create Swing components in the UI thread?

Maybe I should create custom providers which will return Swing components after SwingUtilities.invokeAndWait(Runnable) creates them.

I don't like the idea of running the whole application in UI thread, but maybe it's just a perfect solution.

+1  A: 

In fact, Swing is not multi-threaded and requires to be run in EDT. As a consequence, yes, your components should be prepared in EDT by calling invokeAndWait.

Riduidel
Thanks for the answer. How would you solve it using Guice as the sole creator of Swing components?
Boris Pavlović
Well, you name it : you create your Swing components using invokeAndWait ....ooooh Is Guice mono or multi-threaded ? Because if it does not spawns thread, you can even simplyfi your code by calling your first getInstance() in EDT.
Riduidel
+2  A: 

IMO you should not create components using Guice but services which in turn will create your components. Once you have you service injected it should be easy to make sure that component creation happens on EDT (using invokeAndWait )

eugener
This was the simplest and easiest solution to my problem. I had made an early mistake by extending Swing components and letting Guice instantiating them. After switching to composition, i.e. building services which reference Swing components and having them created explicitly in EDT everything went fine. Application behaves more responsive and there are no more UI glitches.TIP: Substance look and feel is a great tool for testing if Swing code is used outside of EDT.
Boris Pavlović
+1  A: 

You might want to check out my Guts-GUI project (Swing app framework built upon Guice). Guts-GUI makes sure your components, even when created by Guice, are created in the EDT.

Guice itself doesn't provided any way, out of the box, to declare a component to be created in the EDT. I am not sure if Guice Scopes could be used for that (I think yes), however, I am not sure that any Scope-based solution would be worthwhile, in particular regarding performance.

The first step to solving this problem is to make sure that Guice Injector is created from inside the EDT (by using SwingUtilities.invokeAndWait or invokeLater). This is what Guts-GUI does in the first place. Hence, if some components are created early by Guice, they will be created in the EDT.

Then you must ensure that any instances injected by Guice, and that require creation of injected Swing components, are obtained (eg through Injector.getInstance(...)) from the EDT.

jfpoilpret