Have you ever fretted over the difficulty of creating a desktop
application with a Swing-based user interface (UI)? Developers have
sometimes complained that building Swing applications is just too
hard. Sun has taken much of the feedback and has tried to simplify
the process of building Swing-based applications on the desktop. The
recent simplifications have taken shape as two separate Java
Specification Requests (JSRs): JSR 295, Beans Binding, and JSR 296,
the Swing Application Framework.
Although both JSRs focus on the problematic areas common to typical
Swing applications, desktop engineers Hans Muller and Joshua
Marinacci focused on the framework in the session titled "JSR 296:
The Swing Application Framework" (TS-3942). The two predict that the
JSR will be part of the Java SE 7 platform, but you don't have to
wait that long to benefit from their work. The Swing Application
Framework is available online now as Project Appframework on
java.net, where you can find the documentation, code, and samples.
The term framework sometimes causes apprehension because
frameworks can be large, complicated, and overbearing. For small
applications, a framework can introduce more complexity than the
original system they supposedly help. However, the Swing Application
Framework has goals that minimize its size and weight, as well as its
negative effects on your applications.
The framework was built with the following goals:
- To be as small and simple as possible
- To require less than an hour to explain
- To work well for both small and medium applications
Additionally, the framework does not introduce fluff such as docking
frameworks, data models, scripting languages, or graphical user
interface (GUI) markup schema. The framework simply helps provide the
kernel of a typical Swing application.
The framework API supports five main aspects of an application: life
cycle, resources, actions, tasks, and session state.
The framework architecture has two singleton classes that help you
manage your application: ApplicationContext and
Application. The ApplicationContext
provides support for storage, session state, action and resource
management, and task control.
Understanding how to use the framework takes very little time.
Typically, you'll use the framework in four steps:
- Create a subclass of the
Application class for your specific
application.
- Create and show your GUI by overriding a
startup() method.
- Use
ApplicationContext services to manage actions, tasks,
resources, and session state.
- Call
Application.launch() from your application's
main method.
The typical "Hello, World!" application might look like this:
// SingleFrameApplication is a subclass of Application.
public class MyApp extends SingleFrameApplication {
@Override protected void startup() {
JLabel label = new JLabel("Hello World");
show(label);
}
public static void main(String[] args) {
Application.launch(MyApp.class, args);
}
}
Managing Application Life Cycle
Most applications will start with a class that extends the
Application class, usually the SingleFrameApplication
subclass. Your subclass should override the life-cycle methods, which
run on the event dispatch thread (EDT). The life-cycle methods run in
a specific order:
launch() -> initialize() -> startup() -> ready() -> exit() -> shutdown()
Your application will start by calling the
Application.launch() method, which itself calls
initialize(), startup(), and
ready() on the EDT. Override the
initialize() method to perform steps that must occur
before the GUI appears. For example, you should set your UI look and
feel from within the initialize() method. Create your
initial GUI from within the startup() method. All
applications will override startup(). Use the
ready() method to perform any work that should occur
after the GUI is visible. Finally, use the exit() method
to close down your application. The exit() method checks
with ExitListener objects to determine whether the
application can actually shut down. ExitListener objects
can veto exit requests, presumably to finish critical tasks or to
query the user to confirm the exit request.
Managing Resources
Most applications use common resources such as text, icons, colors,
and font definitions. If you ever want to localize your application
to other locales or platforms, you should externalize resources to
facilitate easy modifications or translations to other spoken
languages. Resources are defined in ResourceBundle
classes, and the framework helps you manage resources with
ResourceMaps.
The ResourceMap class encapsulates a list of
ResourceBundle objects. You can define application- or
package-wide resource bundles to organize strings, fonts, or other
platform-specific resources that are retrieved by way of key-value
pairs.
ResourceMap instances support automatic resource
injection. By following a few naming conventions or by using the
@Resource annotation, you can make your application
automatically load and apply text, fonts, colors, and more to UI
components and fields.
The advantage of resource injection is that you don't have to
manually set labels and visual properties. Additionally, your UI
becomes localizable by default.
Creating Actions
An Action class encapsulates an
ActionListener and includes some visual properties and
state. You can reuse Actions in different parts of your
application to perform the same behaviors with different UI elements.
Actions are helpful because they allow you to reuse common text and
behavior among many components, and they can be enabled or disabled
easily. However, creating them is sometimes tedious, and developers
often forget that the visual properties should be localizable. Also,
Action code tends to become tangled and difficult to
manage over time.
The new @Action annotation improves on some of the
weaknesses of Actions, making them more convenient to use.
You can define and use Action annotations for your
methods like this:
@Action public void sayHello() {
String s = textField.getText();
JOptionPane.showMessageDialog(s);
}
// Use sayHello -- set the action property.
Action sayHello = getAction("sayHello");
textField.setAction(sayHello);
button.setAction(sayHello);
The Application.getAction utility method creates and
uses an Action for each @Action method. The
default key is the action's method name, and it caches that
information in an ActionMap. Resources such as text,
icons, and accelerators are loaded from the ResourceMap
of the target class. The ResourceMap gets its
information from resource bundles, and resource injection can
automatically apply the resources from a property file like this:
# resources/MyForm.properties
sayHello.Action.text = Say &Hello
sayHello.Action.icon = hello.png
sayHello.Action.accelerator = control H
sayHello.Action.shortDescription = Say hello
Performing Background Tasks
You should always use a background thread for I/O bound or
computationally intensive tasks. Long-running tasks can block the
EDT. The new framework provides support for starting, stopping, and
monitoring the progress of a background task. Although the
SwingWorker class has most of what's needed, the
framework provides a Task class to support more
functionality. A TaskService class helps you execute
tasks, and a TaskMonitor helps you monitor progress.
Saving Session State
The framework provides a way to save session state. Saving GUI state
allows you to restart the application and return to the same window
or form at a later time. The framework provides
SessionStorage and LocalStorage classes for
those purposes.
Demos, Demos, and More Demos
Marinacci and Muller provided several demos during their
presentation. The demos not only showed off the new framework APIs,
they also showed how well the upcoming NetBeans IDE 6.0 integrates
the framework. This NetBeans IDE release will provide several
plug-ins to make using the framework easier. Additionally, the IDE can
help you generate much of the common scaffolding of a simple
application, which includes menu bars and items for common actions
such as Open, Save, Print, and so on.
Find More Information
If you missed session TS-3942, you can still learn about this
new framework by reviewing source code, documentation, and binaries on the
java.net Project Appframework site.
Don't be shy with questions either. Direct your queries to
the Project appframework email address.
Check out related sessions at the 2007 JavaOne conference:
- Why Spaghetti Is Not Tasty: Architecting Full-Scale Swing Apps (TS-3316), Thursday, 2:50 to 3:50 p.m.
- Beans Binding (TS-3569), Thursday, 4:10 to 5:10 p.m.
Session times and room assignments sometimes change, so check the
online schedule on the JavaOne conference home page for
updates.
|