Vladimir has posted 15 posts at DZone. View Full User Profile

Experimenting with Swing Application Framework

05.19.2008
| 19676 views |
  • submit to reddit

The quality and speed of building a Java-based graphic user interface (GUI) have always been high on the agenda. It is no secret that the development of a graphical interface using Swing requires quite a plenty of time. But it’s not critical if the developer doesn’t have a very deep knowledge of a GUI building. He just needs to write large amounts of code for the creation and adjustment of any graphical component. Sometimes this process becomes quite monotonous and boring and it’s great when you can delegate this routine work with component adjustment to anybody else…

Swing Application Framework library is designed to help with the development of desktop applications that contain GUI. It’s a small set of Java classes, aka “the framework”, that provides a ready-to-use infrastructure for most desktop applications. The use of this library allows to make an application architecture more obvious, and the code “lighter” for understanding and further support. Besides this framework undertakes all the routine operations with the configuration of graphical components, and lets the developer to concentrate on other aspects of application development (realization of business logic etc.).

For each of our products we create a demo application to highlight its major features. For our new product, JxCapture, we also made a small demo application which in fact represents a simple screen capture solution. It’s a common Swing application. The functionality of the application is enabled through a menu accessible through a tray icon, providing settings and an image viewer for a captured image.

Initially, we implemented the demo application using a standard Java Swing library. However, we are always on the look for new ways and technologies that can help us make our products better. Keeping track of the development of the Swing Application Framework, that is designed to help with the desktop application development, we decided to try it out and re-write the existing Swing-based application. The purpose of this “experiment” was to research the capabilities of the framework and possibly to further use it in the development of Java-based desktop applications.

So we had a Swing-based application and decided to write exactly the same one but with the Swing Application Framework.

Application Lifecycle

When we started working we noticed at once how convenient application lifecyle was realized. Swing Application Framework provides a very convenient mechanism for tracking of such events like starting and shutting down an application. For application start we realized all the necessary operations, such as reading of application settings from a configuration file, registration of various listeners, adjustment of graphical components of an application etc.

At application shutdown we carry out all necessary operations required for a correct shutdown: releasingof unused resources, closing streams, removing listeners, saving settings into configuration file.

To launch our application we just needed to inherit the main class of an application from the SingleFrameApplication and to call Application.launch function in the main method. We had no need to wrap the code that launches the application into Event Dispatch Thread. This functionality was already realized in the function Application.launch.

public static void main(String[] args) throws Exception {
launch(JxCaptureDemo.class, args);
}

We were pleasantly surprised that the default look and feel was system-dependant.

Resources

The application framework supports automatically initializing the properties of named components from ResourceBundle resources. That is using “resource injection” we can adjust many parameters of the component simply by naming it! All other parameters that are defined in the appropriate resource file will be set automatically.

We used this mechanism when configuring all graphical components of our application. For example in the dialog “About” we used “resource injection” to adjust most of the components of this dialog. Parameter values for components reside in a special resource file—AboutDialog.properties. This approach is especially convenient for a mixed-language interface. Besides all the data for the graphical components is stored in one place what simplifies the search and replacement of any parameters.

Resources can be used for initialization of class fields as well as for adjustment of component parameters. We just needed to mark required fields with annotation @Resource and to set values in the properties file for these fields. After the command ResourceMap.injectFields was executed all the marked fields were initialized automatically. In most cases the fields were of a simple type (String, int etc.). But in the class ApplicationSettings we used this approach for initialization of fields that represent string arrays. For this purpose we only needed to determine in the properties file the following content:

ApplicationSettings.imageFormats[0] = png
ApplicationSettings.imageFormats[1] = jpeg
ApplicationSettings.imageFormats[2] = bmp
ApplicationSettings.imageFormats[3] = gif

And in the class ApplicationSettings we also needed to make initialization that had the following look:

public final class ApplicationSettings {
@Resource
private String[] imageFormats;

// ...

private ApplicationSettings() {
ApplicationContext context = Application.getInstance().getContext();
ResourceMap resourceMap = context.getResourceMap(ApplicationSettings.class);
imageFormats = new String[resourceMap.getInteger("ApplicationSettings.imageFormats.length")];
resourceMap.injectFields(this);
}

// ...
}

As you can see we had to allot memory for the field imageFormats before initializing this field. It’s a little bit unhandy, because we have to know the exact number of array components. In our case we decided to store the array length in the resource called “ApplicationSettings.imageFormats.length”. Hopefully developers will make memory allotment as a part of the field injection in the future.

Actions

Every desktop application is based on an event model. Using the annotation @Action in SAF we can mark a method that’s intended to serve as the implementation of an Action’s actionPerformed method. The ApplicationContext getActionMap method creates an ActionMap that contains one Action object for each @Action defined by some class. The annotation @Action in our code lets us make it more obvious and easy for perception. So, for example, the realization of events in the class TrayPopupMenu with SAF has the following look:

public class TrayPopupMenu extends JPopupMenu {
private ApplicationSettings settings = ApplicationSettings.getInstance();
private CaptureOperations operations = CaptureOperations.getInstance();
private boolean captureOperationEnabled = true;

// ...

public boolean isCaptureOperationEnabled() {
return captureOperationEnabled;
}

public void setCaptureOperationEnabled(boolean captureOperationEnabled) {
boolean oldValue = this.captureOperationEnabled;
this.captureOperationEnabled = captureOperationEnabled;
firePropertyChange("captureOperationEnabled", oldValue, this.captureOperationEnabled);
}

@Action (enabledProperty = "captureOperationEnabled")
public void activeWindowCapture() {
operations.activeWindowCapture();
}

@Action (enabledProperty = "captureOperationEnabled")
public void objectCapture() {
operations.objectCapture();
}

// ...
}

The realization of the same class using a standard approach requires 30% more code lines! The parameters for each event we described in the appropriate properties file:

activeWindowCapture.Action.text = Capture active window
activeWindowCapture.Action.icon = images/act_window.png
activeWindowCapture.Action.accelerator = control shift A

objectCapture.Action.text = Capture window / object
objectCapture.Action.icon = images/win_obj.png
objectCapture.Action.accelerator = control shift W
...

These @Actions also introduces the enabledProperty annotation parameter which binds the enabled state of the @Action to the current value of a property. Our application settings allow to set assignable delay before capture operation, so that the user could take some actions before this operation takes place, for example he can open/close some windows. It’s advisable to restrict the for the user from performing other operations during this delay. It can be realized for example by disabling them. In our example we have just that case.

The parameter captureOperationEnabled checks if any operation is currently launched. Thanks to the entry @Action (enabledProperty = "captureOperationEnabled") we bind the state of the variable captureOperationEnabled to the state of an event (in our case to the state of all the events that should be disabled when there is already one operation running). It’s very convenient and easy!

Unfortunately it’s possible to define only the method that determines the realization of Action’s actionPerformed method so far. It would be very convenient if we could define parameterized events using annotations. And until then we have only one solution for such cases—to use standard Swing approach which is based on creation of a class that will describe the required event.

Summary

In our application we had no need to use other features of this framework, such as:

  • Persistent session state: support for automatically and selectively saving GUI state, like top level window geometry, from one run of an application to the next.
  • Actions that swap background tasks.

But I’m sure these features will be useful in most desktop applications. This framework is certainly worth using in development of large applications. In most cases Swing Application Framework contains everything that experienced developers may need for their complex applications (application lifecycle, task service or resource management). And even if there’s missing something here, you can always use standard approach.

In whole in spite of some shortcomings mentioned above (or peculiarities if we can say so :-), it was very interesting and easy to re-write with Swing Application Framework an application primarily written using Swing. This framework has a lot of really convenient and practical things. Sometimes its approaches seem to be so obvious that it’s strange that nobody has implemented it earlier. So, long live developers of this framework! They managed to enhance the development process for desktop applications in Java and to make it more interesting and convenient.

Useful Links

Published at DZone with permission of its author, Vladimir Ikryanov.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Nishant Kumar replied on Tue, 2008/05/20 - 2:10am

may be it is just me but I could not get the name of the swing application framework the author is talking about till I figured out that "swing application framework" itself is the name. When I clicked the link at the end of the article I also realized that there is also a JSR for this. Good. Ignorant me.

Benoit Guerout replied on Tue, 2008/05/20 - 2:57am

I think this article talks about :

https://appframework.dev.java.net/

 

Geertjan Wielenga replied on Tue, 2008/05/20 - 2:47am

One of the cool things about the Swing Application Framework is the tooling that NetBeans IDE provides for it, out of the box. Like, wizards and templates as well as the "Matisse" GUI Builder. I have demoed the Swing Application Framework at a few conferences, first without the tooling and then with the tooling. Both scenarios come across very strongly. I particularly like the state persistence across restarts. I hope JSR-296, i.e., the related JSR makes it into the JDK. To me, the Swing Application Framework is the next step up from the JFrame.

Richard Osbaldeston replied on Tue, 2008/05/20 - 10:08am

One less cool thing about Swing Application Framework or JSR 296 is that the lead developer has left the project and it's been left in limbo without any support, misleading documentation or any kind of roadmap or ETA on when (or whether) something might happen to rectify this any time soon. http://www.dzone.com/links/hanss_swan_song.html

It's one of several APIs that are suffering under the long shadow of JavaFX and the losses of key members of staff from Suns Swing team recently. Saw the clearest signal so far that Suns ambitions for JavaFX extend beyond RIA and may even include eclipsing UI development with Swing entirely? http://www.pushing-pixels.org/?p=312

I couldn't recommend doing anything with the either JSR 295, or JSR 296 (or TimingFramework/Transitions) until some of these issues have been resolved and new maintainers found (surely the list can't be all that long). Frankly I find the lack of maintaince & support for these APIs to be shocking and their inclusion into Netbeans was in hindsight premature at best.

Fair enough to have other priorities internally, but to the exclusion of any and all support, bugfixing or news? 

 

Geertjan Wielenga replied on Tue, 2008/05/20 - 10:12am

Richard, frankly, it's hard to argue with anything you've said.

Ashley Aitken replied on Tue, 2008/05/20 - 10:25am in response to: Richard Osbaldeston

My usual comment when I see discussion of the Swing Application Framework is that Java should have had it "ten" years ago.  One of the (many) things that makes Cocoa (and previously the AppKit) on MacOSX so great is its application framework(s).  From what I have seen the SAF was heading in the right direction, although it seems to have some ways to go.   If it is now going to suffer because the lead developer has left Sun then that is just another indication of Sun's neglect of the (traditional) desktop application.  

 That said, I have a question relating to the use of the SAF or one of the RCP (Netbeans or Eclipse).   In the past people have suggested that one of the RCPs is more appropriate for more substantial desktop application (because they were more full-featured, e.g. included a plugin model).  I'm wonderfing now if SAF with OSGi would be a "better" option for more substantial desktop applications.  I sometime thing the RCPs may provide too many constraints on the final application (e.g. in look and feel) although I am not expert in their use.  

Cheers, Ashley.

 

  

Geertjan Wielenga replied on Tue, 2008/05/20 - 10:28am

Well, SAF doesn't provide a lot of things (and that was never its point), such as a docking system, for example. It was always meant for smallish apps and prototypes. As such, it does its job well, but note Richard's caveats.

Peter Karussell replied on Tue, 2008/05/20 - 5:36pm

Yes, the SAF. What a great framework for me as a swing developer!

I played a little bit with it and created an example (included beans binding, picocontainer, jpa):

https://timefinder.svn.sourceforge.net/svnroot/timefinder/trunk/example/SwApp/

But the main reason I will NOT use it for my project is included in the post from Richard. Its a pitty.

Romain Guy replied on Wed, 2008/05/28 - 11:33am

>>or TimingFramework/Transitions

TimingFramework works really well as it is now. Sure, more work would be great, but I don't think it *needs* it. Also, it was revived in a different form as part of the SceneGraph project for JavaFX. The SceneGraph contains an animation engine very similar to TimingFramework, but more powerful.

Evan Summers replied on Fri, 2008/05/30 - 1:49pm

i wonder if it's such a trainsmash for things like SAF et al to be a "third-party" frameworks/libraries in the vein of  popular Apache libraries ie. a de facto bolted-on standard rather than a built-in standard - at least then it can evolve with more freedom eg. as a community opensource project... even tho that can introduce some pain on occassion for application developers eg. when the backwards compatibility is thwarted willy-nilly albeit with good evolutionary reasons.

Walter Dogg replied on Tue, 2009/04/07 - 4:23pm

I was thinking of using SAF.

 Has there been any further developments since Hans Muller left?

 

Thanks

Illya Yalovyy replied on Fri, 2009/09/11 - 2:40pm

http://kenai.com/projects/bsaf/edit

This is a fork of the Swing Application Framework (JSR 296).
Primary goals for the upcoming release:  improve stability, keep backward compatibility with last public release of the SAF (1.03), bug fixing,  documentation update (javadoc, introduction), unit tests update,  examples update.

Carla Brian replied on Sun, 2012/07/15 - 5:27am

This is interesting. I want to learn how to do this one. This might be really interesting and cool. I love it. Good job on this. - James Stuckey

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.