DBS
DBS

Reputation: 63

SwingUtilities InvokeLater- what is considered bad practice?

I've got a question about what would be the correct practice to use the invokeLater method of SwingUtilities.

So to begin, I'd like to confirm that I am understanding it correctly.

From what I understand, changes to the GUI must be done on the EDT, because Swing components aren't thread safe. The invokeLater method takes a Runnable as an argument, and anything contained in that runnable will be run on the EDT. Therefore any calls made to Swing components are put in a kind of queue, which are executed one at a time on the EDT.

With that out of the way, my question then is: what is good practice for using this? From what I can see there are at least two ways to do it:

1) In the main method, place all code, such as GUI creation, Controller creation, and even the Model creation (assuming a MVC type pattern), in a Runnable that is invoked by the invokeLater method. Of course, this is assuming that any long running tasks in the Model would be executed with a SwingWorker.

2) Place GUI creation in a invokeLater, but Controller creation and Model creation in the main method. Then whenever you need to access a Swing component from a Controller, you pop said code in an invokeLater method to place it on the EDT queue.

What one of these two would be considered best practice, or bad practice? And if neither of these two are good, what would be the better way to go about this?

Any info would be hugely appreciated.

Thanks.

Upvotes: 3

Views: 329

Answers (2)

hexstorm
hexstorm

Reputation: 378

That's indeed an interesting question and the accepted answer isn't fully responding it.

Both approaches you suggest are acceptable and will work fine, but I believe the first one is better than the second approach (do it all on the EDT, and if there is some long-running tasks do them on a SwingWorker, or a new thread if they're not related to Swing).


Why? As @ThomasKrägler pointed out here:

While you could split these tasks (model, controller and view creation) between main thread and EDT (and possibly gain a few milliseconds until the UI is first shown) it would also complicate the design of the application (multithreading is no easy topic) and litter the code base with invokeLater() calls.

Take into account that the EDT won't need to process anything until the model and controller are initialised (and thus starting the view too). So you can use the EDT to initialise them, as it won't have any negative impact on your UI (there is no UI yet).

Doing it this way, you'll save a lot of invokeLater calls and possible errors forgetting to call invokeLater. Your code will look much cleaner too.

Upvotes: 2

Charlie
Charlie

Reputation: 9108

SwingWorker isn't special, it's just some wrappers around common scenarios. It will call invokeLater on your behalf so really both cases you present are just instances of the same thing.

Just make sure you follow these two rules: 1. Don't stall the EDT 2. Perform Swing-related code on the EDT

Upvotes: 1

Related Questions