Skip to end of metadata
Go to start of metadata

An example of using threading with SwingBuilder to do lengthy operations in the background so GUI event handling remains responsive. This sample code demonstrates many of the issues that may occur including replacing the content of a "please wait" message with something else, and safely changing "realized" components only on the EDT (Event Dispatch Thread). This sample happens to use tableLayout, which can get pretty slow but that is a good stresser for the demonstration.

Eventually there will be more explanation of what's going on here, but hopefully this will be helpful.

SwingThreading.groovy

  • No labels

3 Comments

  1. This is a good example, but a couple of things could be improved.

    The SwingBuilder.build method in no way indicates it's two primary side effects, (a) creating a brand new SwingBuilder and (b) that it executes in the EDT. The current trunk has a method newBuilderInEDT that makes this more apparent to the casual reader that those two side effects will happen.

    Second, two instances of SwingBuilder are being used when one is all that is needed. The first instance could be changed to

    and the second instance could be changed to

    . In fact, the parameter could either be changed to the SwingBuilder or eliminated entirely if the variables parentPanel and lazyPanelsParent were merged to the same variable.

    Stylistically the calls to parentPanel could also be eliminated with the container() node containing the panel. Here another version with some more of these groovy stylistic changes:

  2. For comparison, here's a roughly equivalent version written in the Java Programming Language. Look at all of those exceptions and anonymous classes. No wonder people get lazy with switching to the EDT.

  3. Both of Danno's alternate versions have subtle but significant differences from mine.

    In the Groovy version, the use of container() means that the position of the new panel gets lost. The point of my version is that the new panel starts building in a particular position in the list of lazy panels (first or last being what might be typical) at the time the building begins. When the lazy panel is finally ready it goes into that same position in the list (which may not be first or last or whatever anymore). That effect can be achieved in other ways though, such as by having an extra panel.

    As for parameters vs. external variables, any use of external variables is trouble prone in multithreaded code and should generally be avoided. Not only do they invite races, but they introduce non-local dependency on the structure of the user interface. By using a parameter rather than an external variable for the parentPanel the background builders may be operating in multiple windows and/or other generalized layouts.

    The Java version misses the bit that buildInBackground may be called from a thread other than EDT. Obviously that can be done, but means just more Java code (further making Danno's point that SwingBuilder beats the heck out of using Java for Swing!).

    Note that my versions works in all versions of Groovy since 1.5.x. And since http://jira.codehaus.org/browse/GROOVY-3177 has not received any additional votes in favor of deprecating static SwingBuilder.build, I expect that it will remain the standard public API that it has been for more than a year.